【发布时间】:2013-09-11 18:41:25
【问题描述】:
这些声明之间有什么区别,我们称它们为红色和橙色: 利弊?
【问题讨论】:
标签: ios objective-c local declaration
这些声明之间有什么区别,我们称它们为红色和橙色: 利弊?
【问题讨论】:
标签: ios objective-c local declaration
红色的集合是属性,橙色的集合是实例变量。
属性声明告诉编译器定义一个 getter 方法,也可能是一个 setter 方法。 (如果属性是只读的,则没有 setter 方法。)
在较新版本的 Objective C 中,声明一个属性也会创建一个实例变量,用于保存该属性的值。按照惯例,实例变量与属性具有相同的名称,但带有“_”前缀。有一种方法可以更改实例变量的名称,但我们暂时忽略它。
属性 foo:
@property (nonatomic, strong) NSString *foo;
会有一个getter方法:
- (NSString *) foo;
还有一个setter方法
- (void) setFoo: (NSString *) foo;
这使您可以使用这样的代码:
NSString *aString = self.foo;
或
NSString *aString = [self foo];
(两种不同的、同样有效的调用 getter 方法)
并调用设置器
self.foo = @"a string";
或
[self setFoo: @"a string"];
(两种不同的、同样有效的调用 setter 方法)
当您想创建一个公共接口以从外部获取和设置类中的值时,属性非常有用。如果您将属性声明为“原子”,则编译器会向 getter 和 setter 添加额外代码,因此对该属性的读写是“线程安全的”,并且可以从后台线程访问。
在 ARC 之前,属性也是管理保留和释放的一种非常简洁的方式。您将一个属性声明为“保留”,并且编写了 setter 来保留传入的对象。这在 ARC 中不是什么问题,因为系统会为您处理保留和释放。
也可以编写自定义的 getter 或 setter 方法来调用您自己的代码,而不是编译器编写的代码。您可以使用它来执行日志信息、发送有关更改的通知、更新标签等操作。您只需将方法主体添加到具有与 getter 或 setter 相同的方法签名的 .m 文件中,编译器就会使用它方法而不是自动生成的方法。
正如我之前所说,代码:
self.foo = @"a string";
和
一样[self setFoo: @"a string"];
并调用setter方法。 setter 方法设置内部实例变量 _foo。
但是代码
_foo = @"a string";
直接改变实例变量,而不调用setter。如果你确实定义了一个属性,你应该使用它而不是实例变量。
【讨论】:
Objective-c 使用起来很简单……而且很乏味。您将为一个类(橙色)声明实例变量,然后(通常)为每个定义 2 个方法,一个是为了让外部类可以将每个实例变量设置为一个新值,另一个是返回 ivars 值,因此外部对象可以读取它。 Aka,您必须为每个 ivar 编写一个 getter 和 setter。这是接口中的两行代码,有时大约 10 行代码用于实现文件。
然后是属性,用@property 声明。街上有许多欢乐和饮酒。这些单一的@property 行告诉编译器为您编写这些方法,包括正确的内存管理代码甚至互斥锁代码(取决于您在声明@property 时指定的内容)
有很多历史,但是现在,有了自动引用计数,只有在你想要公开 ivar 并在你的实现文件中声明你的私有 ivar 时,在你的界面中使用 @properties 才有意义。
最后,并不是说@property 不仅告诉编译器实现你的getter 和setter,它还自动提供一个同名的实例变量,但前缀为下划线(这只有在你有属性的隐式合成时启用...更多历史记录)
所以,这就是区别。 @property 告诉编译器(本质上)为您编写代码。它实际编写的代码会通过您可以声明@property 的所有不同方式进行修改。
【讨论】: