NSString属性和自定义init

时间:2013-10-04 11:48:11

标签: objective-c nsstring initialization init nscopying

我有两个问题。

首先 - 在obj-c

中声明字符串
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *city;

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

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

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

或者我应该使用:

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

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

感谢。

2 个答案:

答案 0 :(得分:11)

您希望将copy用于值语义类型属性。 (其中NSString总是一个。)否则,我可以传递一个NSMutableString的实例,然后在事后将其从你的下方改掉。不可变对象将通过-copyWithZone:实现return [self retain];以便在不需要时不会实际创建第二个副本。另见:NSString property: copy or retain?

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

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

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

对于泄露的内存,如果你正在使用ARC,当foo是self.foo = [bar copy];属性时,执行类似copy的操作将导致副本被调用两次,并且可能正在制作两个副本,但ARC应该正确地释放冗余/中间副本,并且应该是内存泄漏。

答案 1 :(得分:0)

首先 - 如果您使用copystrong,这并不重要。我个人更喜欢复制字符串而不是保留它们

第二 - “

-(id)initWithName:(NSString *)n andCity:(NSString *)c

   {
      self = [super init];
       if (self) {
          self.name = n;
          self.city = c;
  }
}`

您不需要再次使用copy消息,因为您的属性会复制n和c。如果你应用第二段代码,你将复制n和c两次并有内存泄漏