一个101问题
假设我正在制作汽车数据库 每个汽车对象定义为:
#import <UIKit/UIKit.h>
@interface Car:NSObject{
NSString *name;
}
@property(nonatomic, retain) NSString *name;
为什么是@property(nonatomic, retain) NSString *name;
而不是@property(nonatomic, assign) NSString *name;
?
我了解assign
不会像retain
那样增加引用计数器。但是为什么要使用retain
,因为name
是todo
对象的成员,它的范围就是它自己。
其他任何外部功能都不会修改它。
答案 0 :(得分:68)
Objective-C中没有“对象的范围”这样的东西。范围规则与对象的生命周期无关 - 保留计数就是一切。
您通常需要声明实例变量的所有权。见the Objective-C memory management rules。使用retain
属性,您的属性设置器声明新值的所有权并放弃旧值的所有权。使用assign
属性,周围的代码必须执行此操作,这在责任和关注点分离方面同样混乱。您将使用assign
属性的原因是您无法保留该值(例如BOOL或NSRect等非对象类型),或者保留它会导致不必要的副作用。
顺便说一下,在NSString的情况下,正确的属性通常是copy
。这样,如果有人传入NSMutableString(它是有效的 - 是一种NSString),它就无法从你身下改变。
答案 1 :(得分:19)
并且不要忘记通过
访问它self.name = something;
,因为
name = something;
不关心生成的setter / getter方法,而是直接赋值。
答案 2 :(得分:12)
如果没有retain
,则无法保证NSString*
name
设置retain
的时间超过赋值语句本身。通过对合成setter使用NSString*
属性,您可以让它告诉内存管理系统至少还有一个对象需要保留{{1}}。
答案 3 :(得分:9)
对于那些正在寻找它的人,Apple关于属性属性的文档是here。
答案 4 :(得分:9)
self.
in:
self.name = something;
很重要!没有它,您将直接访问变量并绕过setter。
旧样式(如果我错了,请纠正我)本来是:
[self setName:something];
无论如何,这个符号是我在@properties
寻找合适NSStrings
时真正需要的(含糊不清的声音)建议。谢谢阿克塞尔。
答案 5 :(得分:8)
在阅读了如此多的文章,SO帖子和制作演示应用以检查变量属性属性后,我决定将所有属性信息放在一起
以下是详细的文章链接,您可以在其中找到上述所有属性,这些属性将极力帮助您。 非常感谢所有在这里给出最佳答案的人!!
示例:
@property (nonatomic, retain) NSString *name;
@synthesize name;
示例:
@property (nonatomic, assign) NSString *address;
@synthesize address;
答案 6 :(得分:3)
Google的Objective-C Style Guide非常清楚:
Setters采用NSString,应该始终复制它接受的字符串。 永远不要只保留字符串。这可以避免调用者在您不知情的情况下将其更改为您。不要假设因为你接受的NSString实际上并不是NSMutableString。
答案 7 :(得分:2)
如果你的班级得到这个字符串对象然后它从它下面消失了,那会不幸吗?你知道,就像你的班级第二次提到那个对象一样,它被另一个对象解除了吗?
这就是你想要使用retain
setter语义的原因。