2010-04-29 61 views
22

我試圖創建一個只讀屬性。我想用創建該類實例的類中的值進行初始化,例如正在初始化只讀屬性

@property (retain,readonly) NSString *firstName;

我試着初始化它是這樣的:

-(id)initWithName:(NSString *)n{ self.firstName = n; }

一旦我這樣做,編譯報道,只讀屬性不能分配錯誤。那我該怎麼做呢?

回答

13

不要使用合成的二傳:

firstName = [n retain]; //Or copy 

通常建議反正繞過任何init和dealloc的方法的制定者。

+0

我上面的實現的問題是,值不被保留。一旦我將保留添加到屬性中,該賦值是否將該值設置爲屬性。如果其他對象訪問此屬性,此值將在那裏。我也修改了我的問題 – awsome 2010-04-29 11:17:10

+0

爲什麼這會成爲問題?使用'firstname = [n retain]'將使firstName成爲'n'的指針。所以是的,當其他一些對象訪問這個屬性時,值就會在那裏。 :) – Rengers 2010-04-29 11:39:49

+0

如果我嘗試這樣做,如果我訪問此屬性,我得到以下異常。程序收到信號:「EXC_BAD_ACCESS」。而這個錯誤不是由於任何其他財產。我在調試器中進行了很多調查。該屬性顯示「超出範圍」。如果我分配它,self.firstName = n;。那麼一切正常。 – awsome 2010-04-29 13:13:39

38

要麼直接分配給實例變量(如果需要,不要忘記添加retaincopy),或者重新聲明私有類擴展中的屬性。就像這樣:

在您的.h文件中:

@property (readonly, copy) NSString *firstName; 

在您.m文件:

@interface MyClass() 

// Redeclare property as readwrite 
@property (readwrite, copy) NSString *firstName; 

@end 


@implementation MyClass 

@synthesize firstName; 
... 

現在你可以使用合成的二傳手在您的實現,但類的接口仍然顯示財產只讀。請注意,導入.h文件的其他類仍然可以調用-[MyClass setFirstName:],但它們不會知道它存在並將得到編譯器警告。

+0

這看起來是一個很好的解決方法。謝謝。 – awsome 2010-04-29 11:30:03

+0

與使用@Renger建議的方法相比,使用合成的setter有什麼優勢? – Madbreaks 2012-12-19 20:23:23

2

您可以直接訪問屬性:

_firstName = n;

self.firstName = n意味着不會因爲你@property (retain,readonly) NSString *firstName;指定readonly,因此編譯器錯誤合成的setter方法。

+0

沒有_firstName ... – 2016-04-06 10:56:07

+0

這是我的理解,_firstName將存在。這是在宣佈財產時創建的基礎伊娃。從Xcode 4.6開始,編譯器應該自動爲你創建。 – Bob9630 2016-05-05 16:36:25

+0

這就是我的理解@Bob9630。對於這個問題的其他答案在我的情況下沒有產生期望的結果,雖然這樣做。 – 2016-05-05 23:47:51