目标C:哪个改变了,属性还是ivar?

时间:2012-06-08 09:58:28

标签: iphone objective-c xcode4.2 ivar

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

当我进入我的.h时:

@interface SecondViewController : UIViewController{    
NSString *changeName;    
}

@property (readwrite, retain) NSString *changeName;

然后在我的.m

@synthesize changeName;

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

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

3 个答案:

答案 0 :(得分:7)

你(似乎其他一些人回答)是属性与实际变量混淆。

属性的工作方式是,它们创建设置或获取/返回ivars的METHODS(称为setter和getter)。并且符号(self.string)实际上隐藏了这些方法。所以属性不能被改变,只有声明的iVar是。

当你声明一个这样的属性时:

@property (nonatomic, retain) NSString *string;

并且@synthesize它发生以下情况:

  • 创建一个名为string(类型为NString *)的iVar

    (如果你这样做

    @synthesize string = whateverYouWant
    
    iVar创建了 被称为whateverYouWant - 一种惯例是命名iVars 与前面下划线(_string))

  • 的属性相同
  • 像这样创建一个访问器方法

    -(NSString*) string;
    
  • 像这样创建一个setter

    -(void) setString: (NSString*) newString;
    

现在self.xxxx的作用是,它实际上将消息xxxx发送给self (比如[self xxxx])。 它适用于任何方法,而不仅仅是属性,尽管它应该只有 与属性一起使用。

所以当你做self.string = @“hello”时,它实际上归结为

[self setString: @"hello"];

(注意,编译器实际上知道你正在尝试设置等等 发送setString消息而不是只发送字符串。如果您访问self.string 它会发送[self string])

因此你没有设置属性,你调用了(合成的)setter方法 本身设置了iVar。

如果您知道自己在做什么,可以直接访问iVar。 只需致电

string = @"something else";

将产生泄漏代码,因为没有进行内存管理。 合成的访问器和setter实际上是为你做的,取决于 关于如何定义属性(保留,复制,分配)。

因为setter(对于保留属性)不仅仅是

IVar = newValue

如果您声明了保留属性,它实际上看起来像这样:

-(void) setString: (NSString*) newString {
  if (string) [string release];
  string = [newString retain];
 }

所以属性合成需要你手上的一些工作。

修改

由于它似乎仍然不清楚,因此不会考虑声明的属性 像一个变量。在上面的例子中,当使用

@synthesize string = _string;

没有名为“string”的变量。这就是您访问方法结构的方式 通过setter方法设置iVar _string。由于string不是变量/对象指针,因此无法向其发送消息([string doSomething]将无效)。 当你使用@synthesize字符串合成属性时;生成的iVar得到了 与财产同名。 然后调用[string doSomething]将起作用,但它与属性无关。 “字符串”指的是iVar。因此,强制命名iVars的约定如此 当你打算使用getter / setter时,你不会意外地访问iVar。

答案 1 :(得分:2)

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

通常为了区分ivars和属性,人们使用_前缀来表示ivars。然后合成这样的属性:

@synthesize myProperty=_myProperty;

答案 2 :(得分:2)

好吧,var

总是var

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

现在,请考虑这种情况:

self.changeName = @"changed";

这种方式你使用的是属性,但这只是意味着你正在使用编译器,setter和getter方法“神奇地”为你创建的方法,你再次更改var(属性不会实际上,它只是一种为你创建setter和getter方法的方法。)