2010-11-04 49 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:,并在那里做你自己的定制逻辑是可能的,但是它没有框架支持。