2011-11-19 73 views
8

所以,我已經注意到這KVC和Properties之間有什麼區別?

的Objective-C 2.0的點語法和鍵值編碼正交技術文檔上閱讀了。無論您是否使用點語法,都可以使用鍵值編碼,無論您是否使用KVC,都可以使用點語法。兩者都使用「點語法」。在鍵值編碼的情況下,語法用於在鍵路徑中分隔元素。請記住,使用點語法訪問屬性時,需要調用接收方的標準存取方法。

然後,它提供了一個例子,據說顯示兩者之間的差異。但是,我仍然不明白,KVC和property accessor方法有什麼區別?他們不一樣嗎?如何區分調用setValue:forKeyPath的點和簡單訪問器?

回答

14

不過,我還是不明白,什麼是KVC和屬性訪問方法之間的區別?

KVC是調用屬性訪問器方法或以其他方式訪問屬性的一種方法。

「否則訪問」是什麼意思?對於KVC而言,沒有訪問器方法的實例變量會被視爲非正式屬性。如果沒有找到匹配的訪問器對,它將直接獲取或設置實例變量的值。 (是的,這在現代代碼中是不值得使用的,對於任何你想要訪問的任何東西,總是聲明一個@property,反過來也不要使用KVC來訪問任何非公有財產。)

屬性訪問器方法是KVC在存在的情況下會調用的方法(KVC和每個理智的程序員都優先考慮直接ivar訪問)。訪問者可以獲取或設置實例變量,如合成訪問者所做的那樣,或者訪問某些其他存儲。

訪問器是實現,屬性是接口,KVC是使用它們的一種方式。

我該如何區分調用setValue的點:forKeyPath:和簡單訪問器?

關鍵路徑是一個字符串,而屬性訪問表達式是一個表達式。編譯器評估屬性訪問表達式並將其轉換爲一個或多個Objective-C消息,而關鍵路徑由KVC在運行時評估。

所以,當你使用一個關鍵路徑:

[someObject setValue:theValue forKeyPath:@"foo.bar.baz"]; 

你知道這是一個關鍵的路徑,因爲(1)它是一個字符串,在這種情況下,由字符串文本語法@"…"表示,和(2 )您將密鑰路徑字符串傳遞給setValue:forKeyPath:以供其評估。

使用關鍵路徑使用KVC訪問指定的屬性。它會代表您發送任何相關的訪問者消息。

當您使用屬性的訪問表達:

someObject.foo.bar.baz = theValue; 

你知道這是一個屬性訪問表達式,因爲你不是識別與字符串的屬性。您正在使用自己的代碼訪問它們(發送訪問者消息)。

沒有什麼理由以任何形式使用KVC;當您在作者/編譯時知道該屬性時,最好聲明一個@property並自行訪問該屬性,無論是使用屬性訪問表達式還是消息表達式([[[someObject foo] bar] setBaz:theValue])。使用KVC的時間是在運行時間之前不知道要訪問的屬性,這很少見。它主要是KVO,Cocoa Bindings,Core Animation等部分背後的構建塊技術。

大多數情況下,您只需要自己訪問屬性。

+4

**「使用KVC的時間是當你不知道你想訪問什麼屬性,直到運行時間」**從你的答案是我正在尋找,謝謝。 – km3h

+0

這對我真的很有幫助。我在腦海裏認爲**使用KVC的時間是在運行時間之前不知道你想訪問什麼屬性,**這可能是原因,但我不確定。你讓我相信我的想法。 –

+0

彼得你陳述「,反過來說,不要使用KVC來訪問任何非公共財產。「我發現如果一個屬性聲明爲只讀,然後在實現中重新聲明爲讀寫,那麼KVC將無恥地寫入該屬性。是否沒有辦法阻止它?我試過(BOOL)accessInstanceVariablesDirectly {返回NO;}但這並不妨礙KVC寫入屬性 –

2

鍵值編碼允許您使用屬性的字符串名稱通過代碼設置和獲取屬性的值。例如,如果我有一個名爲foo的屬性,其類型爲NSString:

[self setValue:@"mystring" forKey:@"foo"]; 

// read the value by key 
NSString *s = [self valueForKey:@"foo"]; 

點語法是編譯語法糖。作爲一個個人喜好(如一些不同意 - 罰款)我不使用點語法,但我仍然可以使用KVC:

[myObj setFoo: @"someString"] 

等於:

myObj.foo = @"someString"; 

他們是正交的,不同的概念,但兩者都涉及您如何與屬性進行交互

最後,您提到屬性語法。又一個正交的概念,但涉及到處理財產。

使用objective-c,約定很重要。跟着他們。屬性是屬性爲GET的名稱並設置[名稱]的任務:

- (NSString*)foo 
{ 
    return _foo; // defined as (NSString*)_foo in header 
} 

- (void) setFoo: (NSString*)foo 
{ 
    if (foo == _foo) 
     return; 

    NSString* curr = _foo; 

    _foo = [foo retain]; 
    [curr release];  
} 

現在,誰願意寫這樣的事情每次。在.M

@property (retain) NSString *foo; 

然後:那麼,進入@property語法:

在頭

@synthesize foo; 

這就是手寫屬性訪問的等價物。它是編譯器語法糖,它根據屬性的屬性來擴展屬性代碼。

文檔:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html

相關問題