2013-10-27 41 views
7

我有A類,它揭示了一種獲取和設置Foo類型的對象的方法。在屬性的說法,我一般聲明這在界面:如何聲明@property但是防止創建它的ivar?

@property (nonatomic, strong) Foo * foo; 

這(在現代ObjC)同時生成訪問器和用於存儲的實例變量,_foo

如果我想在訪問器中進行自定義工作,我可以自己實現其中的一個或兩個。但是如果我不僅想做定製工作,我其實不想要伊娃?換句話說,我正在用Foo對象做其他事情,就像來回交給另一個我與之合成的內部對象。我實際上並不需要在A的實例中保留foo的存儲空間。

好像我有兩個選擇:

  1. 申報財產,同時實現存取,並簡單地忽視的事實是編譯器爲_foo創建存儲,而從不使用它。
  2. 明確聲明我的訪問者:- (Foo *)foo- (void)setFoo:(Foo *)foo在接口中,就像我在前現代的ObjC中使用的一樣。

第一個在運行時看起來不雅觀,第二個在聲明中似乎不夠優雅(我現在可能有混合了屬性和屬性的訪問器)。

有沒有辦法來聲明一個屬性,並將其作爲純粹的聲明?

回答

4

如果同時覆蓋setter和getter和不使用變量在setter和getter中,變量將不會被創建。

舉例來說,如果你有一個類,你想要一個firstNamelastName財產,但也許也是一個fullName財產settergetter,如果你的fullName制定者只需將字符串解析firstNamelastName並設置這些屬性(並且永遠不會將整個字符串存儲到變量fullName中),並且您的fullName getter只是returns級聯的firstName + lastName並且從不使用fullName變量,因此永遠不會創建它。

這是根據蘋果的官方文檔。 Scroll down to "You Can Implement Custom Accessor Methods"

+0

你是對的!感謝文檔指針,我錯過了。我發現這種行爲對我的口味有點神奇,但很高興知道這一點。 –

+0

正如你可能在文檔中已經注意到的那樣,你可以聲明屬性爲'readonly'或'writeonly'並覆蓋該訪問器並避免創建該變量。 – nhgrif

9

在實現文件中使用@dynamic關鍵字。 @dynamic的通常討論將其描述爲在編譯時不創建訪問器。通常不會提到的是,也會產生無用的功能,以便爲屬性創建存儲,這正是在這種情況下所期望的。

@implementation A 
@dynamic foo; 

- (Foo *)foo 
{ 
    // get a Foo from somewhere and return it. 
} 

- (void)setFoo:(Foo *)foo 
{ 
    // do something with foo 
} 

@end 

(注:回答我的問題,因爲我發現這一點,而寫了這個問題,它似乎有趣的和非顯而易見的)

+0

+1'@ dynamic'是我比較中意的東西之一。 –

2

@dynamic可能是要走的路。

然而,還有其他兩種方法可以做到這一點還有:

  1. 未實現分類

    您可以使用一個未實現的類別申報財產,但沒有得到的支持存儲:

    @interface Foo : NSObject 
    @end 
    
    @interface Foo (UnimplementedProperties) 
    @property (strong) id bar; 
    @end 
    
    @implementation Foo 
    @end 
    

    通過不聲明類別(@implementation Foo (UnimplementedProperties))的實施方式中,屬性將不被合成。

  2. 一個協議

    您可以在協議聲明屬性,然後讓你的類符合該協議。這與未實現的類別具有相同的效果:聲明方法,但不合成屬性。

    @protocol FooProperties <NSObject> 
    @property (strong) id bar; 
    @end 
    
    @interface Foo : NSObject <FooProperties> 
    
    @end 
    
+0

偉大的觀點,謝謝。這些缺點是,對象的消費者在標題中看到了這種區別,但只要我從他們的角度理性地行事,我的調用者就不應該如何管理財產。 –

+0

@BenZotto同意,這就是爲什麼你應該使用'@ dynamic'。但是這些方法也有其用處。 :) –

+0

是的,我沒有想到這些模式會產生我以前做過的事情的副作用。謝謝。 (無論如何,事實證明,也許我們都試圖在任何情況下都很努力,請參閱@ nhgrif的答案。) –

相關問題