0

担心重复但似乎无法找到并回答我可以在任何其他帖子中理解,我只需要问:

当我在我的 .h 中时:

@interface SecondViewController : UIViewController{    
NSString *changeName;    
}

@property (readwrite, retain) NSString *changeName;

然后在我的.m

@synthesize changeName;

-(IBAction)changeButton:(id)sender{
changeName = @"changed";
}

当我按下“changeButton”时,是合成属性还是实例变量发生了变化?

4

3 回答 3

7

您(似乎其他一些回答的人)将属性与实际变量混淆了。

属性的工作方式是,它们创建设置或获取/返回 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。

于 2012-06-08T10:11:39.097 回答
2

两个都。属性使用实例变量作为其存储。在您的代码中,您更改了实例变量,但如果您访问该属性(通过self.changeName),您将获得与实例变量相同的值。

通常为了区分 ivars 和属性,人们使用_ivars 的前缀。然后合成如下属性:

@synthesize myProperty=_myProperty;
于 2012-06-08T10:03:55.980 回答
2

好吧,var

它始终是 var

在您的情况下,根本不使用属性方法。

现在,考虑这种情况:

self.changeName = @"changed";

这样您就可以使用该属性,但这仅意味着您正在使用编译器为您“神奇地”创建的方法,setter 和 getter 方法,您再次更改 var(属性不存在,在实际上,这只是为您创建 setter 和 getter 方法的一种方式)

于 2012-06-08T10:04:39.203 回答