保留和复制

时间:2011-12-31 08:52:08

标签: objective-c ios copy retain

我认为我已理解retaincopy之间的区别。但是当我遇到下面的代码时,我又一次感到困惑。这些是代码:

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

任何人都可以解释为什么结果是:

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

?感谢。

1 个答案:

答案 0 :(得分:4)

首先,-retainCountuseless to you

其次,一个误解就是复制属性实现的实现。你没有像预期的那样得到这里的副本。相反,您获得[arg copy]而不是[arg mutableCopy]的结果。许多不可变类型'复制'本身就像这样(简化):

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

所以结果最终会是:

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!

因为它们是不可变的和纯粹的,所以这在语义上是合理的。它还意味着如果类型区分了不可变类和可变副本,则需要自己为可变类型实现副本访问器。否则,当您尝试变异ivar时,您的程序可能会爆炸,因为您持有不可变实例。如果您将其添加到-viewDidLoad的末尾,则会看到例外:[self.c appendString:@"uh-oh"];

More detail on implementing a mutable property here