使用ARC覆盖@property setter @property并使用'copy'

时间:2014-02-15 14:57:50

标签: ios objective-c automatic-ref-counting

@interface Unicorn
@property (nonatomic, copy) NSString *name;
@end

是这样的吗?

- (void)setName:(NSString *)name
{
   _name = name;
}

或者是这样的?

- (void)setName:(NSString *)name
{
   _name = [name copy]; 
}

2 个答案:

答案 0 :(得分:9)

你应该做第二次。

如果覆盖setter,则可以控制复制与非复制的语义。 ARC将在插入保留/释放方面做正确的事情,但不会为您调用copy

我的来源?测试它

@interface UnicornWithCopyCall : NSObject

@property (nonatomic, copy) NSString *name;

@end

@implementation UnicornWithCopyCall

- (void)setName:(NSString *)name
{
  _name = [name copy];
}

@end

@interface UnicornWithOutCopyCall : NSObject

@property (nonatomic, copy) NSString *name;

@end

@implementation UnicornWithOutCopyCall

- (void)setName:(NSString *)name
{
  _name = name;
}

@end

然后用

练习
UnicornWithCopyCall *unicorn = [[UnicornWithCopyCall alloc] init];
unicorn.name = name;

NSLog(@"%p %p", name, unicorn.name);

UnicornWithOutCopyCall *unicornWithOutCopyCall = [[UnicornWithOutCopyCall alloc] init];
unicornWithOutCopyCall.name = name;

NSLog(@"%p %p", name, unicornWithOutCopyCall.name);

没有复制调用,指针是相同的,而使用复制调用,您将获得一个新对象,这是一个副本。

答案 1 :(得分:3)

它应该是第二个。第二部分完全是可选的,但如果新值与旧值不同,有时只设置字符串会有所帮助。这个例子是按值的,这意味着_namename是否引用同一个对象无关紧要,当两个对象包含相同的值时,检查将起作用,但你可以很容易参考比较。

- (void)setName:(NSString *)name
{
    if (![_name isEqualToString:name]) {
        _name = [name copy];
    }
}

这是CocoaWithLove

的另一个例子
- (void)setStringValue:(NSString *)aString
{
    if (stringValue == aString)
    {
        return;
    }
    NSString *oldValue = stringValue;
    stringValue = [aString copy];
    [oldValue release];
}