Objective c NSString属性和自定义初始化

Objective c NSString属性和自定义初始化,objective-c,nsstring,initialization,init,nscopying,Objective C,Nsstring,Initialization,Init,Nscopying,我有两个问题 首先-字符串在obj-c中声明为 @property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *city; 那些(非原子,复制)是正确的还是我应该使用(非原子,强),或者其他什么 Second-如果我想为上述字符串设置自定义初始值设定项,我应该使用吗 -(id)initWithName:(NSString *)n andCity:(NSString *)c { self

我有两个问题

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

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *city;
那些
(非原子,复制)
是正确的还是我应该使用
(非原子,强)
,或者其他什么

Second-如果我想为上述字符串设置自定义初始值设定项,我应该使用吗

-(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];
    }
}
正如我所看到的,两种方法似乎都适用于两个问题,但我确信其中一种方法比另一种更正确,因此我想问,在以后的项目中,我应该使用哪种方法来编写正确的代码


谢谢。

首先-使用
copy
strong
并不重要。就我个人而言,我更喜欢复制字符串而不是保留它们

第二-`

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

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

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

您希望对值语义类型属性使用
copy
。(其中,
NSString
始终是一个)否则,我可以向您传递一个
NSMutableString
的实例,然后在事实发生后将其从您下面更改出来。不可变对象将通过执行
返回[self-retain]
来实现
-copyWithZone:
;这样就不会在不需要的时候创建第二个副本。另见:

-init
方法而言,您希望避免像以前那样使用属性设置器,因为它们可以在子类中被重写,以执行类无法预见的操作。因此,假设默认的自动ivar合成命名模式,您需要执行以下操作:

-(id)initWithName:(NSString *)n andCity:(NSString *)c
{
    if (self = [super init])
    {
        _name = [n copy];
        _city = [c copy];
    }
    return self;
}
这是一件微妙的事情,通常不会成为问题,但如果您继续在
-init
-dealloc
方法中使用固有的虚拟财产设置器,在足够长的时间内,您会被这烧死(您能告诉我我被烧死了吗?)


至于泄漏的内存,如果您使用的是ARC,则执行类似于
self.foo=[bar copy]
当foo是
copy
属性时,将导致copy被调用两次,并可能生成两个副本,但ARC应注意正确释放冗余/中间副本,并且不应出现内存泄漏。

如果使用
copy
strong
相比,这非常重要。使用
strong
我可以向您传递一个
NSMutableString
的实例,然后在事后将其从您的下方更改出来。这就是为什么值语义属性应该始终是
copy
。不可变对象将通过执行
返回[self-retain]来实现
-copyWithZone:
以便在不需要时不实际创建第二个副本。