2013-01-01 28 views
7

可能重複:
How does an underscore in front of a variable in a cocoa objective-c class work?self.variableName與_variableName與@sysnthesize VARIABLENAME


注:對於鄉親們四處想明白這一點,我找出了我混亂的根源。在.h中,我有:

... 
@interface myClass : parentClass { 
className *variableName: 
} 

@property (strong, nonatomic) className *variableName; 
... 

這導致self.variableName和_variableName是.m中的兩個不同的變量。我需要的是:

... 
@interface myClass : parentClass { 
className *_variableName: 
} 

@property (strong, nonatomic) className *variableName; 
... 

然後,在類的.M,self.variableName和_variableName是等價


在全新的Xcode的4.5+,與ARC,瞄準的iOS 5.0 +項目,使用_variableName而不是self.variableName與舊式@synthesize variableName相比有沒有明顯的優勢(運行效率,速度等)?

我的理解是,Xcode中4.5+將創建一個默認的訪問_variableName等效於self.variableName,唯一的理由不使用@synthesize variableName是避免實例變量和傳入的變量,正確之間的混亂呢?

對我而言,僅僅使用self.variableName來訪問一個iVar似乎是最直接,最清楚你正在尋找哪個變量。除了打字_self.之外,使用_variableName還有什麼優勢?

+1

這裏還有另外16:http://stackoverflow.com/q/5582448/ http://stackoverflow.com/q/6049269/ http://stackoverflow.com/q/2371489/ HTTP:/ /stackoverflow.com/q/7174277/ http://stackoverflow.com/q/5659156 http://stackoverflow.com/q/837559/ http://stackoverflow.com/q/6146244/ http: //堆棧溢出。com/q/10651535/ http://stackoverflow.com/q/6124109/ http://stackoverflow.com/q/8145373/ http://stackoverflow.com/q/3521254/ http:// stackoverflow.com/q/6064283/ http://stackoverflow.com/q/9696359/ http://stackoverflow.com/q/5521499/ http://stackoverflow.com/q/5466496/ http: //stackoverflow.com/q/2114587/ –

+0

我的不好。我不會想到搜索拼寫出來的'下劃線'。也就是說,檢查一些潛在的二重奏,如果使用_variableName而不是自我,我沒有看到關鍵值觀察,綁定和線程安全訪問(原子)潛在問題的任何/新手證明。 。變量名。其中一個(4088801)提到了一個潛在的問題,如果在_variableName中引用的對象是共享的並且建議使用self.variableName來代替。 –

+0

如果您發現在整個問題的許多實例中有一個被忽略的特定問題,您當然可以隨時詳細詢問。然而,將這些信息恰好埋入另一份副本中幾乎沒有什麼價值。 –

回答

15

我的理解是,Xcode中4.5+將創建一個默認的訪問「_variableName」,也就是相當於self.variableName,唯一的理由不使用「@synthesize VARIABLENAME」是爲了避免實例變量之間的混淆傳入變量,正確嗎?

在這種情況下,_variableName不存取,這是由編譯器自動生成,並在自動@synthesized setter和getter使用的ivar。通常,儘可能使用訪問器被認爲是最好的(即self.variableName),這樣鍵值觀察和綁定等功能就可以用於該屬性。

當你直接訪問一個ivar時,它通過直接內存訪問來訪問,就像訪問一個結構中的數據一樣。它只需要擁有該ivar的對象的指針,抵消內存地址並嘗試讀取或寫入該位置的內存。使用點符號(self.variableName)調用存取方法來設置或獲取財產,可以做一些沿途不同的東西,如:

1)鎖定:如果屬性將在使用多線程並且屬於atomic屬性,則運行時將自動執行一些鎖定操作,以確保不會從多個線程同時訪問該屬性。如果您的對象不打算在多個線程中使用,則可以在屬性聲明中提供nonatomic提示,以便合成訪問器跳過鎖定。

2)關鍵值通知:默認setter方法屬性調用-willChangeValueForKey:-didChangeValueForKey:,其中,當所述屬性更改發出通知。如果使用綁定和任何其他鍵值觀察,這對於正確更新的任何內容都是必需的。

3)自定義訪問器行爲:如果您最終編寫自己的setters和getters,那麼您在那些實現的自定義的東西。

從技術上講,直接訪問伊娃是比使用訪問者更快,但是很少有情況會導致顯着的性能差異,並可能是過早優化的情況。即使你不覺得你會立即使用上面列出的好處,但最好還是使用訪問器,以便稍後決定需要某些功能時,不必更改每個實例訪問該變量(可能會在流程中創建意外的新錯誤)。此外,如果您直接訪問ivars並最終將您的課程重構爲類別或子類,它會變得雜亂無章,因爲您通常必須將伊娃爾聲明爲變量@protected。如果您使用訪問器,則不必執行此操作。

通常,我嘗試只在init,dealloc和屬性的訪問器中直接訪問ivars。許多工程師按照這個經驗法則,因爲有時在訪問器中發生的自定義事件可能會導致意外行爲,而對象是init'或dealloc'。例如,如果訪問器中的任何內容導致對象retainrelease對象或甚至形成對它的調零弱引用,則在dealloc中使用時會導致崩潰。

5

在最新的Xcode @synthesize是可選的。默認情況下,省略@synthesize是一樣的書寫

@synthesize someName = _someName; 

使用@synthesize重命名創建存儲屬性的值實例變量的唯一原因,例如

@synthesize someName = someSpecialName; 

當你使用self.variableName來訪問一個變量,你需要通過一個屬性,這是一個訪問實例變量的簡短方法。儘管派遣方法速度非常快,但它可能會爲您執行其他服務,例如同步對變量的訪問(當您在屬性聲明中指定atomic或未指定nonatomic時,就是這種情況)。在這種情況下,通過self.variableName的訪問會稍微慢一些。如果在緊密的環路中完成,這可能會有所作爲。這就是爲什麼你有時想通過使用_variableName直接訪問底層實例變量的原因。

+0

只是要迂腐,根據您的回覆和@eyebrowsoffire,_variableName,可能會更快,但self.variableName更安全? –

+0

@RayatERISCorp在這種情況下,「安全」是未定義的,但如果您的目的是以同步的方式使用屬性(即它是「原子」),那麼答案是肯定的,它更安全。事實上,另一種方式(即直接使用'_variableName')在沒有額外鎖定的情況下無法正常工作。 – dasblinkenlight

+0

Gotcha。通過「更安全」我的意思是「不太可能觸發我的代碼中的一些意外錯誤,這會讓我調試時間比我應該做的時間長得多,因爲使用_variableName不會自動啓動self.variableName所執行的某些操作。」 –

相關問題