Defining your own key path operators in cocoa
Is it possible to define your own key path operators, such as @avg开发者_运维问答, @sum, etc…
Short answer: Kinda. You can override valueForKeyPath:
to intercept your custom operator or forward on to super
, but that can be problematic (I'll leave the explanation to that as an exercise to the reader).
Long answer: Yes you can, but it relies on using private behavior (not private api).
After some neat introspection of NSArray
, I found some private methods:
_distinctUnionOfSetsForKeyPath:
_distinctUnionOfObjectsForKeyPath:
_distinctUnionOfArraysForKeyPath:
_unionOfSetsForKeyPath:
_unionOfArraysForKeyPath:
_unionOfObjectsForKeyPath:
_minForKeyPath:
_maxForKeyPath:
_countForKeyPath:
_avgForKeyPath:
_sumForKeyPath:
Well, neat! Those methods seem to match the operators you can use with collections: @sum
, @min
, @max
, @distinctUnionOfObjects
, etc. The @
has been replaced with an underscore and we've got ForKeyPath:
appended.
So it would seem that we can create a new method to match the appropriate signature and we're good to go.
So:
@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!"
It works, but I'm not sure I would rely on this, since it relies on an implementation detail that could change in the future.
It's possible by overriding valueForKeyPath:
and doing your own custom logic in there, but there's no framework support for it.
精彩评论