self.ivar和ivar之间的区别?

时间:2010-11-10 07:36:09

标签: iphone objective-c ios

aclass.h

@interface aClass : NSObject {
    NSString *name;
}

@property (nonatomic, retain) IBOutlet NSString *name;

@end

aclass.m 

@implementation aClass

@synthesize name;

- (void)dealloc {
    [name release];
    [super dealloc];    
}

- (void)test1 {
    name = @"hello";
}

- (void)test2 {
    self.name = @"hello";
}

以上面为例。有人可以解释name = @"hello"self.name = @"hello"之间的区别吗?谢谢!

编辑:后续问题:How to write my own setter for an ivar, i.e.: self.ivar = ...?

4 个答案:

答案 0 :(得分:64)

要知道,这个帖子已经老了!

这篇文章来自前十年。

请务必阅读下面的重要脚注,欢呼!!


当你刚入门时,很难理解这一切。

以下是一些简单,实用的经验法则 FOR BEGINNERS

重复一遍,这篇文章是 FOR BEGINNERS

此处的目的是让您快速从起跑线移动到能够在大多数情况下自信地使用该系统。

稍后,您可以真正了解这些问题的内部运作。

(1)不要说name=@"hello"总是说 self.name=@"hello"。在项目范围内搜索name并确保在设置或更改时始终说self.name而不是name

(2)你知道关于内存管理,初始化,发布等所有令人生气的事情。如果你使用自己的东西,它会照顾你所有的东西。好吧?

(3)自我特别有用,因为你可以轻松地“改变”字符串(或其他任何东西)。所以,这样做完全没问题,

self.name=@"aa";  
self.name=@"bb";  
self.name=@"cc";  

而(一句话)你永远不会,出于任何原因,这样做 ......

name=@"aa";
name=@"bb";
name=@"cc";

(*)关于您的字面问题,“请解释name = @"hello"self.name = @"hello"?"之间的区别这很容易做到。

第一个是仅设置变量。你知道,就像过去生活很简单,我们13岁时的"x=42"一样。

第二个是完全不同的,特别是它正在调用一个复杂的例程(称为“setter”)来为你做很多令人惊讶和惊人的事情。

这就是你问题的字面答案。 第一个只是设置变量(并且不要忘记,有很多指针和其他奇怪的东西涉及,并且通常你肯定不能像那样设置指针。 第二个实际上是一个很复杂的例程,因此会为你做很多事情。

再一次,第二个就像说...

[name bigComplicatedRoutineHere:@"hello"];

...始终记住语法self. ... 实际上是调用例程非常有用。

事实上,一些关于该主题的思想家认为,当他们将self.X语法引入[X complicatedThingHere]时,这是一个愚蠢的想法。它引起了很多困惑,并且每个初学者都会问你究竟是在问什么

就个人而言,我花了九年多的时间才明白这一点。 :-)所以,我再次强调,你必须记住,当你说self.x时,事实上,你实际上是在做一个常规

重复:“自我点”语法实际上调用例程。 (事实上​​,我相信其中一个预处理器只是将其扩展为[x amazingStuffHere]。)

我尝试以一种让您继续前进并允许您推进和使用更多功能的方式回答,同时了解内存管理,属性等。如果你比这篇文章更先进,那就忽略它。

请注意,这篇文章旨在为初学者提供建议,使他们能够继续前进而不会被激怒。希望它有所帮助!


2014年更新!有关初学者的ARC的重要说明......

注意,这篇文章现在五年了!它已被成千上万的初学者阅读,并有许多后续问题等。请注意,今天在新的“ARC世界”。在某种程度上:如果你是初学者:你应该只使用!! 属性。即,随时随地使用“self.whatever”。无论如何,请注意这篇文章中的信息“基本上是历史性的”,并且每天都变得越来越多。当然,不言而喻,一旦您成为专家,您将需要并将了解所有这些细节。希望它可以帮到某人。

答案 1 :(得分:32)

self.name使用您定义的访问器和/或增变器(这是非原子的并保留在您的情况下)。因此,当您调用self.name = foo时,它将调用编译器生成的setName:(NSString *)str mutator,它将首先释放当前字符串,然后保留新字符串,最后将name设置为保留字符串。

只是调用name = foo只会为foo指定名称。

这也意味着您只能在为ivar定义属性时调用self.xxx,否则编译器会告诉您它不知道它(iVar)。

答案 2 :(得分:6)

name = @“Joe”

您正在直接访问该变量,绕过了Cocoa为您创建麻烦的getter方法。通常,这不是最明智的事情。

self.name = @“Joe”

现在,您将通过您要求cocoa为您创建的方法。这通常是最好的方法。

根据经验,始终使用Cocoa提供的setter和getter,但有一个例外:dealloc。在dealloc中,您应该始终直接释放变量,而不是通过getter方法:

-(void) dealloc {
   [name release]; // instead of [[self name] release]
   ...

   [super dealloc];
}

在dealloc中避免访问器的原因是,如果子类中有观察者或覆盖触发行为,它将从dealloc触发,这几乎不是你想要的(因为对象的状态将是不一致)。

OTOH,还有一种稍微方便的语法来声明你可能不知道的iVars。如果您只定位64位mac,则可以使用属性生成访问器方法和实例变量本身:

#import <Cocoa/Cocoa.h>
@interface Photo : NSObject 
@property (retain) NSString* caption; 
@property (retain) NSString* photographer; 
@end

答案 3 :(得分:-2)

这是真正的内存管理,属性语法是真正的setter和getter方法,当使用self.xxx =?时,它可以调用setter方法,对象保留cout +1,名称不能释放,但如果名称= foo与属性语法无关。

setter方法示例:

-(void)setObj:(ClassX*) value 
{  
         if (obj != value) 
         { 
                   [obj release]; 
                   obj = [value retain]; 
         } 
}