54

一个 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它的范围是它自己。

也没有其他外部函数会修改它。

4

8 回答 8

68

在 Objective-C 中没有“对象的范围”这样的东西。范围规则与对象的生命周期无关——保留计数就是一切。

您通常需要声明实例变量的所有权。请参阅Objective-C 内存管理规则。对于retain财产,您的财产设定者要求拥有新价值的所有权并放弃旧价值的所有权。对于assign属性,周围的代码必须这样做,这在职责和关注点分离方面同样混乱。使用assign属性的原因是您无法保留该值(例如 BOOL 或 NSRect 等非对象类型),或者保留它会导致不必要的副作用。

顺便说一句,在 NSString 的情况下,正确的属性类型通常是copy. 这样,如果有人传入 NSMutableString(这是有效的——它一种 NSString),它就不会从你下面改变。

于 2009-09-04T17:47:03.210 回答
19

并且不要忘记通过

self.name = something;

因为

name = something;

不会关心生成的 setter/getter 方法,而是直接分配值。

于 2011-01-11T16:23:46.510 回答
12

如果没有retain,则无法保证NSString*您设置name的时间会比赋值语句本身的寿命更长。通过使用retain综合设置器的属性,您可以让它告诉内存管理系统至少还有一个对象对保持NSString*周围感兴趣。

于 2009-09-04T17:09:41.757 回答
9

对于那些正在寻找它的人,Apple 关于属性的文档在这里

于 2011-01-11T16:06:05.763 回答
9

self.

self.name = something;

很重要!没有它,您将直接访问变量并绕过设置器。

较旧的样式(如果我错了,请纠正我)是:

[self setName:something];

@properties无论如何,这个符号是我在寻找正确的on时真正需要的(听起来有点熟悉的)建议NSStrings。谢谢阿克塞尔。

于 2011-06-21T05:42:53.057 回答
8

在阅读了这么多文章、SO 帖子并制作了演示应用程序来检查变量属性属性后,我决定将所有属性信息放在一起

  1. 原子的 //默认
  2. 非原子的
  3. 强=保留//默认
  4. 弱= unsafe_unretained
  5. 保持
  6. 赋值 //默认
  7. unsafe_unretained
  8. 复制
  9. 只读
  10. 读写//默认

所以下面是详细的文章链接,您可以在其中找到上述所有属性,这将极大地帮助您。非常感谢所有在这里给出最佳答案的人!!

iOS 中的可变属性属性或修饰符

  1. 保留=强
    • 它被保留,旧值被释放并被分配
    • 保留指定应发送新值 -retain 分配并发送旧值 -release
    • 保留与强相同。
    • 苹果说如果你写保留它只会自动转换/像强一样工作。
    • 像“alloc”这样的方法包括一个隐含的“retain”

例子:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. 分配
    • assign 是默认值,只是执行变量赋值
    • assign 是一个属性属性,它告诉编译器如何综合该属性的 setter 实现
    • 对于 C 原始属性,我会使用 assign ,对 Objective-C 对象的弱引用使用 weak。

例子:

@property (nonatomic, assign) NSString *address;

@synthesize address;
于 2013-03-21T07:20:17.537 回答
3

Google 的Objective-C 风格指南很好地涵盖了这一点:

采用 NSString 的设置器应始终复制它接受的字符串。永远不要只保留字符串。这样可以避免来电者在您不知情的情况下更改它。不要因为你接受一个 NSString 而假设它实际上不是一个 NSMutableString。

于 2012-03-12T17:18:46.253 回答
2

如果你的班级得到了这个字符串对象,然后它又从它下面消失了,那会很不幸吗?你知道,就像你的班级第二次提到那个对象一样,它已经被另一个对象释放了?

这就是您要使用retainsetter 语义的原因。

于 2011-01-11T16:13:30.543 回答