NSString属性和自定义init

Žel*_*ber 5 initialization objective-c init nsstring nscopying

我有两个问题.

首先 - 在obj-c中声明字符串

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *city;
Run Code Online (Sandbox Code Playgroud)

那些是(nonatomic, copy)正确的还是应该使用(nonatomic, strong),还是其他什么?

第二 - 如果我想为上面的字符串设置自定义初始值设定器,我会使用

-(id)initWithName:(NSString *)n andCity:(NSString *)c
{
    self = [super init];
    if (self) {
        self.name = n;
        self.city = c;
    }
}
Run Code Online (Sandbox Code Playgroud)

或者我应该使用:

-(id)initWithName:(NSString *)n andCity:(NSString *)c
{
    self = [super init];
    if (self) {
        self.name = [n copy]
        self.city = [c copy];
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以看到两种方式似乎都适用于这两个问题,但我确信一个方法比另一个方法更正确,所以我想问一下我应该用哪些方法在其他项目中编写正确的代码.

谢谢.

ipm*_*mcc 11

您希望copy用于值语义类型的属性.(其中一个NSString总是一个.)否则,我可以通过你一个实例,NSMutableString然后在你之后将它从你下面改掉.不可变对象将-copyWithZone:通过执行来实现return [self retain]; 以便在不需要时不会实际创建第二个副本.另请参见:NSString属性:复制还是保留?

就您的-init方法而言,您希望避免使用属性设置器,因为它们可以在子类中重写,以执行您的类无法预见的操作.因此,假设默认的auto-ivar-synthesis命名模式,您可能希望这样做:

-(id)initWithName:(NSString *)n andCity:(NSString *)c
{
    if (self = [super init])
    {
        _name = [n copy];
        _city = [c copy];
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

这是一个微妙的事情,它通常不会成为一个问题,但如果你继续使用固有的虚拟属性设置器-init-dealloc方法,在足够长的时间线上,你被这个烧掉(你能说我一直都是烧这个?)

至于泄露的内存,如果你正在使用ARC,那么做一些事情就像self.foo = [bar copy];foo copy属性一样导致副本被调用两次,并且可能产生两个副本,但是ARC应该负责正确地释放冗余/中间副本,并且应该没有内存泄漏.

  • 我认为必须接受这个答案而不是我的答案 (2认同)