Определение собственных операторов пути в cocoa

Можно ли определить собственные операторы пути, такие как @avg, @sum и т.д.

Ответы

Ответ 1

Короткий ответ: Kinda. Вы можете переопределить valueForKeyPath:, чтобы перехватить ваш пользовательский оператор или переслать его на super, но это может быть проблематично (я оставлю объяснение этому как упражнение для читателя).

Длинный ответ: Да, вы можете, но он полагается на использование частного поведения (не private 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

Это возможно за счет переопределения valueForKeyPath: и выполнения вашей собственной логики там, но для него нет поддержки фреймворка.