2010-11-04 51 views
15

是否可以定義自己的鍵程運營商,如@avg,@sum等..定義自己的關鍵路徑運營商在可可

+2

我必須不斷努力將'可可'問題發送到烹飪現場...' – 2010-11-04 20:17:40

+2

+1這是一個非常吸引人的問題;一個我從來沒有想過要問的問題,但是卻揭示了一些非常有趣的信息。感謝問! – 2010-11-04 21:13:15

回答

14

簡答:有點。您可以覆蓋valueForKeyPath:來攔截您的自定義運營商或轉發到super,但這可能會產生問題(我會將解釋作爲練習留給讀者)。

長的答案:是的,你可以,但它依賴於使用私人行爲(而不是私人API)。

NSArray一些巧妙的反省後,我發現了一些私有方法:

_distinctUnionOfSetsForKeyPath: 
_distinctUnionOfObjectsForKeyPath: 
_distinctUnionOfArraysForKeyPath: 
_unionOfSetsForKeyPath: 
_unionOfArraysForKeyPath: 
_unionOfObjectsForKeyPath: 
_minForKeyPath: 
_maxForKeyPath: 
_countForKeyPath: 
_avgForKeyPath: 
_sumForKeyPath: 

好,整齊!這些方法似乎與您可以與集合使用的運算符相匹配:@sum,@min,@max,@distinctUnionOfObjects等。@已被替換爲下劃線,我們已追加ForKeyPath:

因此,我們似乎可以創建一個新的方法來匹配適當的簽名,我們很好。

所以:

@interface NSArray (CustomOperator) 

- (id) _fooForKeyPath:(NSString *)keyPath; 

@end 

@implementation NSArray (CustomOperator) 

- (id) _fooForKeyPath:(NSString *)keyPath { 
    //keyPath will be what comes after the keyPath. In this example, it will be "self" 
    return @"Hello world!"; 
} 

@end 

NSArray * array = [NSArray arrayWithObjects:@"1", @"2", @"3", nil]; 
NSLog(@"%@", [array valueForKeyPath:@"@foo.SELF"]); //logs "Hello world!" 

它的工作原理,但我不知道我會靠這個,因爲它依賴於實現的細節,可能在未來改變。

+2

重寫'-valueForKey:'而不是我會。閱讀關於NSDictionary如何實現它的文檔。 – 2010-11-04 21:53:56

+1

@Mike從長遠來看,它可能會更穩定,但重寫的問題是這些操作符通常只對集合有用,並且對集合進行子類化很不好。 :( – 2010-11-04 21:56:50

+1

不錯,找到戴夫!但是,它看起來像你說的那麼脆弱。爲什麼你認爲重寫valueForKeyPath:更危險? – cfischer 2010-11-04 22:00:12

0

它通過重寫valueForKeyPath:,並在那裏做你自己的定製邏輯是可能的,但是它沒有框架支持。