3

这些声明之间有什么区别,让我们称它们为红色和橙色:优点,缺点?

红色和橙色声明

4

2 回答 2

5

红色的集合是属性,橙色的集合是实例变量。

属性声明告诉编译器定义一个 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];

(2 种不同的、同样有效的调用 getter 的方法)

并调用 setter

self.foo = @"a string";

或者

[self setFoo: @"a string"];

(两种不同的、同样有效的调用设置器的方法)

当您想要创建一个公共接口以从外部获取和设置类中的值时,属性非常有用。如果您将属性声明为“原子”,编译器会向 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。如果你确实定义了一个属性,你应该使用它而不是实例变量。

于 2013-09-07T22:51:37.637 回答
4

Objective-c 使用起来很简单……而且很乏味。您将为一个类(橙色)声明实例变量,然后(通常)为每个定义 2 个方法,一个是为了让外部类可以将每个实例变量设置为一个新值,另一个是返回 ivars 值,因此外部对象可以读取它。Aka,您必须为每个 ivar 编写一个 getter 和 setter。这是接口中的两行代码,有时大约 10 行代码用于实现文件。

然后是属性,用@property 声明。街上有许多欢乐和饮酒。这些单个@property 行告诉编译器为您编写这些方法,包括正确的内存管理代码甚至互斥锁代码(取决于您在声明@property 时指定的内容)

有很多历史,但是现在,有了自动引用计数,只有当你想公开一个 ivar 并在你的实现文件中声明你的私有 ivar 时,在你的界面中使用 @properties 才有意义。

最后,并不是说@property 不仅告诉编译器实现你的getter 和setter,而且它还自动提供一个同名的实例变量,但前缀为下划线(这只有在你启用了属性的隐式合成的情况下.. .更多历史)

所以,这就是区别。@property 告诉编译器(本质上)为您编写代码。它实际编写的代码会通过您可以声明@property 的所有不同方式进行修改。

于 2013-09-07T22:55:18.633 回答