Objective-C對象只是一個C堆,它在堆上分配(或多或少)。當你聲明一個實例變量(ivar)時,它被定義爲該結構的偏移量。因此,如果手動宣佈一些高德這樣的(不要做這種方式了,但它說明了這一點):
@interface Foo : NSObject {
NSString *ivar1;
NSString *ivar2;
}
然後,當你+alloc
一個新的實例(稱之爲foo
),該結構將是一些標題後跟NSObject的ivars後跟ivar1
的內存,然後是ivar2
的內存。 ivar1
將爲foo
加上一些偏移量。 (這是不完全正確了,但留下來陪我,這是容易理解的舊的實現。)
由於foo
是一個指向一個struct,你其實可以直接引用這個偏移指針爲foo->ivar1
。它確實是一個結構。切勿這樣做,但它是合法的語法。
在@implementation
區塊內部,ivar1
被自動翻譯爲self->ivar1
。不要太擔心如何實現self
,但相信它是一個指向你的結構的指針。再次,不要使用這種->
語法。這是一個潛在的實現細節(並不總是可能的,見下文)。好吧,這就是伊娃是一個什麼樣的公司。在過去的時間(ObjC 1.0),這實際上就是我們所有的。你聲明你的ivars,然後你手工創建訪問器方法來設置和返回它們的值。
然後,ObjC2出現了,在某些情況下,這也給了我們一種叫做非脆弱ABI的東西。這在一定程度上改變了ivars的底層實現,所以你不能總是實際使用->
。但是你不應該使用它。即便如此,假裝事情是舊的方式更簡單。更重要的是,ObjC2增加了這個名爲「屬性」的新東西。財產只是實現某些方法的承諾。所以,當你說:
@property (nonatomic, readwrite, strong) NSString *property;
這幾乎是相同的說法如下:
- (NSString *)property;
- (void)setProperty:(NSString *)aProperty;
(所不同的是很少重要的。)請注意,這並沒有提供一個實現。它不創建ivars。它只是聲明瞭一些方法。
現在在ObjC1中,我們一遍又一遍地寫了相同的訪問器代碼。你有20個可寫入的Ivars,你寫了40個訪問器方法。他們幾乎完全相同。很多機會搞砸了。和很多乏味。謝天謝地Accessorizer。
使用ObjC2,如果您添加了@synthesize
,編譯器會免費爲您提供最常見的實現。它會自動製作一個與該財產同名的伊娃,並且寫一個吸氣劑和(如果需要的話)二傳手來讀寫伊娃。通過=_property
只是改變了使用的伊娃爾的名字。我們稱之爲「支持伊娃。」
現在,在最新版本的編譯器中,你甚至不需要@synthesize
。這種模式非常普遍,幾十年來一直是默認的,除非你告訴編譯器不要這樣做。它會自動合成帶有下劃線的伊娃(這是最佳做法)。
你應該知道的另一條信息是你應該總是使用訪問者訪問伊娃,甚至在對象內部。唯一的例外是init
和dealloc
方法。在那裏你應該直接訪問伊娃(使用領先的下劃線)。
Thanks Rob ... This is very helpful。 – RichWalt
+1好帖子。總是喜歡對歷史的解釋。 – NJones
好評,NJones ...歷史確實有助於理解當前狀態下的事物是如何/爲什麼。 – RichWalt