您(似乎其他一些回答的人)将属性与实际变量混淆了。
属性的工作方式是,它们创建设置或获取/返回 ivars 的方法(称为 setter 和 getter)。而 do 表示法 (self.string) 实际上会调用这些方法。所以一个属性不能改变,只有声明的 iVar 是。
当你像这样声明一个属性时:
@property (nonatomic, retain) NSString *string;
并且@synthesize 它会发生以下情况:
创建了一个名为 string(NString* 类型)的 iVar
(如果你这样做
@synthesize string = whateverYouWant
创建的 iVar 称为whateverYouWant - 惯例是将 iVar 命名为与前面带有下划线 (_string) 的属性相同的名称
像这样创建访问器方法
-(NSString*) string;
像这样创建一个setter
-(void) setString: (NSString*) newString;
现在 self.xxxx 所做的是,它实际上将消息 xxxx 发送给自己(如 [self xxxx])。它适用于任何方法,而不仅仅是属性,尽管它只能与属性一起使用。
所以当你做 self.string = @"hello" 它实际上归结为
[self setString: @"hello"];
(请注意,编译器实际上知道您正在尝试设置,因此会发送 setString 消息而不仅仅是字符串。如果您访问 self.string,它将发送 [self string])
因此,您无需设置属性,而是调用本身设置 iVar 的(合成的)setter 方法。
如果您知道自己在做什么,直接访问您的 iVar 是可以的。只是打电话
string = @"something else";
将产生泄漏代码,因为没有进行内存管理。合成的访问器和设置器实际上为您执行此操作,具体取决于您如何定义属性(保留、复制、分配)。
因为设置器(用于保留属性)不只是做
IVar = newValue
如果您声明了一个保留属性,它实际上看起来像这样:
-(void) setString: (NSString*) newString {
if (string) [string release];
string = [newString retain];
}
因此,属性合成需要您完成一些工作。
编辑
由于它似乎仍然不清楚,因此声明的属性不应被视为变量。在上面的例子中,当使用
@synthesize string = _string;
没有称为“字符串”的变量。这只是您访问通过 setter 方法设置 iVar _string 的方法结构的方式。由于 string 不是变量/对象指针,因此您无法向其发送消息([string doSomething] 不起作用)。当您使用@synthesize 字符串合成属性时;生成的 iVar 获得与属性相同的名称。然后调用 [string doSomething] 将起作用,但它与属性无关。“字符串”指的是 iVar。因此,将 iVar 命名为下划线的约定,因此当您打算使用 getter/setter 时,您不会意外访问 iVar。