Smeegol
Smeegol

Reputation: 2098

On retain and copy

I thought I had understand the difference between retain and copy. But when I met the code below I became confused again. These are the code:

ViewController.h:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController {
    NSMutableString *a;
    NSMutableString *b;
    NSMutableString *c;
}

@property (nonatomic, copy) NSMutableString *a;
@property (nonatomic, copy) NSMutableString *b;
@property (nonatomic, copy) NSMutableString *c;

@end

ViewController.m:

#import "ViewController.h"

@implementation ViewController

@synthesize a, b, c;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.a = [[NSMutableString alloc] initWithFormat:@"%@", @"aaa"];
    NSLog(@"a:%d", a.retainCount);

    self.b = a;
    NSLog(@"a:%d", a.retainCount);
    NSLog(@"b:%d", b.retainCount);

    self.c = b;
    NSLog(@"a:%d", a.retainCount);
    NSLog(@"b:%d", b.retainCount);
    NSLog(@"b:%d", c.retainCount);
}

@end

can anybody explain why the result is:

2011-12-31 16:54:50.244 RetainCopy[5783:207] a:1
2011-12-31 16:54:50.246 RetainCopy[5783:207] a:2
2011-12-31 16:54:50.246 RetainCopy[5783:207] b:2
2011-12-31 16:54:50.247 RetainCopy[5783:207] a:3
2011-12-31 16:54:50.247 RetainCopy[5783:207] b:3
2011-12-31 16:54:50.248 RetainCopy[5783:207] b:3

? Thanks.

Upvotes: 2

Views: 276

Answers (1)

justin
justin

Reputation: 104718

First, -retainCount is useless to you.

Second, one misunderstanding is in the implementation of the copy property implementation. You're not getting a copy here as you would expect. Instead, you are getting the result of [arg copy] rather than [arg mutableCopy]. Many immutable types 'copy' themselves like so (simplified):

- (id)copyWithZone:(NSZone*)zone
{
  return [self retain];
}

so the result would ultimately be:

NSMutableString * a = [[NSMutableString alloc] initWithString:@"aaa"];
NSString * b = [a copy]; // << returns an immutable copy!
NSString * c = [b copy]; // << immutable to immutable probably just retains itself!

Since they are immutable and pure, this is semantically sound. It also means that you will need to implement copy accessors for mutable types yourself if the type makes a distinction between an immutable and a mutable copy. Otherwise, your program could blow up when you attempt to mutate the ivar because you are holding an immutable instance. If you add this to the end of -viewDidLoad, you should see an exception: [self.c appendString:@"uh-oh"];

More detail on implementing a mutable property here.

Upvotes: 4

Related Questions