主要是涉及到內存管理的問題。self.propertyName 使用self. 是對屬性的訪問。使用_ 是對局部變量的訪問。
ios
全部被聲明爲屬性的成員,在ios5 以前須要使用編譯器指令@synthesize 來告訴編譯器幫助生成屬性的getter,setter方法。以後這個指令能夠不用人爲指定了,默認狀況下編譯器會幫咱們生成。 編譯器在生成getter,setter方法時是有優先級的,它首先查找當前的類中用戶是否已定義屬性的getter,setter方法,若是有,則編譯器會跳過,不會再生成,使用用戶定義的方法。 也就是說你在使用self.propertyName 時是在調用一個方法。如你上面的例子:編碼
- (NSMutableArray *)programStack { if (_programStack == nil) _programStack = [[NSMutableArray alloc] init]; return _programStack; }
這是屬性programStack的getter方法,是你定義的,上面提到編譯器會跳過幫你生成getter方法,使用你本身在類中定義的。當咱們使用self.programStack 來訪問時這個getter方法就會被調用。
spa
這個方法中作了什麼? 它判斷局部變量_programStack 是否爲空,若是爲空,建立實例,並返回。也就是說咱們在使用self.programStack 時能保證它有實例,不爲空再看下面的這個方法,經過上面的說明,你應該能明白爲何使用 _programStack 來添加對象時,獲得的是nil.code
- (void)pushOperand:(double)operand { [self.programStack addObject:[NSNumber numberWithDouble:operand]]; // [_programStack addObject:[NSNumber numberWithDouble:operand]]; }
那是由於_programStack 局部變量自己指向的就是一個空對象nil. 而使用self.programStack 時,會調用上面的programStack方法,在這個方法中將_programStack指向了一個已實例的對象。orm
總結:1,self.是對屬性的訪問,使用它的時候編譯器會判斷_是否爲空,爲空的話自動實例化。會自動訪問get和set方法對象
2,_是對實例變量的訪問,咱們沒有實例化它,不能使用
內存
3,對類裏局部變量訪問使用_,外部變量則用self.
get
4,在getter方法中,不要再使用self。不然會重複調用getter方法,形成死循環編譯器
注意事項:it
手動管理內存的狀況下:
使用「.」語法來初始化變量的時候,會產生內存泄漏的問題:
self.nameArray = [NSMutaleArray alloc] init];
上述代碼,形成的問題是,在self.nameArray的時候至關於調用了set方法,引用計數+1,後面alloc的時候,引用計數再次+1。
在咱們最後dealloc中release的時候,引用計數只減了一次,並無完成所有釋放,這樣就形成了內存泄漏的問題。
解決方法:就是用「_」來初始化以及訪問變量,這樣就不會產生內存問題,雖不是什麼高明的辦法,但的確有效。
_nameArray = [NSMutaleArray alloc] init];
上述即是「.」和「_」在使用的時候的簡單區別。
若是是在ARC(自動管理內存)的狀況下雖然不存在上述問題,但從編碼規範來考慮,仍是注意點兒的好。