在cocoa中定义自己的关键路径运算符

cfi*_*her 15 cocoa objective-c key-value-coding

是否可以定义自己的关键路径运算符,例如@ avg,@ sum等...

Dav*_*ong 14

简短回答:有点儿.您可以覆盖valueForKeyPath:以拦截您的自定义操作符或转发到super,但这可能会有问题(我会将解释作为练习留给读者).

答案很长:是的,你可以,但它依赖于使用私人行为(不是私人api).

经过一些巧妙的反省NSArray,我发现了一些私有方法:

_distinctUnionOfSetsForKeyPath:
_distinctUnionOfObjectsForKeyPath:
_distinctUnionOfArraysForKeyPath:
_unionOfSetsForKeyPath:
_unionOfArraysForKeyPath:
_unionOfObjectsForKeyPath:
_minForKeyPath:
_maxForKeyPath:
_countForKeyPath:
_avgForKeyPath:
_sumForKeyPath:
Run Code Online (Sandbox Code Playgroud)

好吧,整洁!这些方法似乎与您可以收藏使用的运营商:@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!"
Run Code Online (Sandbox Code Playgroud)

它有效,但我不确定我会依赖它,因为它依赖于将来可能会改变的实现细节.

  • 覆盖`-valueForKey:`而不是我愿意.阅读有关NSDictionary如何实现它的文档. (2认同)