我有两个问题。
首先 - 在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];
}
}
我可以看到两种方式似乎都适用于这两个问题,但我确信一个方法比另一方更正确,所以我想问一下我应该用哪些方法在其他项目中编写正确的代码。
感谢。
答案 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)
首先 - 如果您使用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两次并有内存泄漏