56

self在调用 时,在 Objective-C 中使用下划线和使用关键字有区别@property吗?

财产声明:

@property (weak, nonatomic) NSString *myString;

调用@synthesize属性:

@synthesize myString = _myString;

如果我想在我的代码中使用它有区别吗?什么时候?在 getter/setter 中?

self.myString = @"test";
_myString = @"test";
4

4 回答 4

84

self.myString = @"test";完全等同于写作[self setMyString:@"test"];。这两个都在调用一个方法。

您可以自己编写该方法。它可能看起来像这样:

- (void)setMyString:(NSString*)newString
{
    _myString = newString;
}

因为您使用@synthesize了 ,所以您实际上不必费心编写该方法,您可以让编译器为您编写它。

因此,从查看该方法来看,调用它似乎与为实例变量赋值完全相同,对吧?好吧,这不是那么简单。

首先,您可以编写自己的 setter 方法。如果你这样做,你的方法会被调用,它可以做各种额外的事情以及设置变量。在这种情况下, usingself.myString =将调用您的方法,但 do_myString =不会,因此将使用不同的功能。

其次,如果你曾经使用过 Key Value Observing,编译器会做一些非常聪明的技巧。在幕后,它继承了您的类,并覆盖了您的 setter 方法(无论是您自己编写的还是通过综合生成的),以便willChangeValueForKey:对 Key Value Observing 工作所需的调用进行调用。你不需要知道它是如何工作的(虽然如果你想睡前阅读它会很有趣!),但你需要知道如果你想让 Key Value Observing 自动工作,你必须使用 setter 方法。

第三,即使您依赖 synthesize 来编写 setter 方法,也可以调用该方法,这为您未来提供了灵活性。每当值更改时,您可能想要做一些额外的事情,并且当您发现您想要这样做时,您可以手动编写一个 setter 方法 - 如果您习惯于始终使用self.myString =,那么您将不需要更改其余代码以开始调用新方法!

第四,同样适用于子类。如果其他人要对您的代码进行子类化,如果您使用设置器,那么他们可以覆盖它们以调整功能。

每当您直接访问实例变量时,您都没有明确地提供一种方法来连接额外的功能。由于您或其他人将来可能想要挂钩此类功能,因此一直使用 setter 是值得的,除非有充分的理由不这样做。

于 2012-04-26T12:49:01.227 回答
9

你是对的 - 第一个版本 ( self.myString) 调用合成的 getter/setter,第二个版本直接访问私有成员变量。

看起来您正在使用 ARC,所以在这种情况下,它并没有太大的区别。但是,如果您不使用 ARC,则可能会有所不同,因为直接分配给私有成员不会触发使用synthesize.

于 2012-04-26T12:37:48.140 回答
3

_下划线)只是一个约定,如本问题所述。

当您不使用 为属性访问添加前缀时self.,您将直接访问底层变量,就像在 ac 中一样struct。通常,您应该只在您的 init 方法和自定义属性访问器中执行此操作。这允许计算属性和KVC 之类的东西按预期工作。

于 2012-04-26T13:07:56.747 回答
0

There is a tip not mentionend, the access using underscore is faster and the access using self is safer (KVC). Maybe this can summarise when you have to use each one.

于 2018-08-07T08:13:19.153 回答