避免嵌套 KVO 键路径中硬编码字符串的最佳方法

Best way to avoid hardcoded strings in nested KVO keypaths

当通过 KVO 注册观察一个对象时,我写了这段代码来避免硬编码字符串:

[myObject addObserver:self
           forKeyPath:NSStringFromSelector(@selector(myProperty))
              options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
              context:NULL];

注意 NSStringFromSelector。如果我更改了 myProperty 的名称而忘记了观察它的东西,它会在编译时保护我。

但使用嵌套属性时情况会更复杂,例如"myProperty1.myProperty2"

我天真的解决方案是使用如下宏:

#define KEYPATHSTRING1(a) NSStringFromSelector(@selector(a))
#define KEYPATHSTRING2(a, b) [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(a)), NSStringFromSelector(@selector(b))]
#define KEYPATHSTRING3(a, b, c) [NSString stringWithFormat:@"%@.%@.%@", NSStringFromSelector(@selector(a)), NSStringFromSelector(@selector(b)), NSStringFromSelector(@selector(c))]

有更好的或标准化的解决方案吗?对 Google 和 SO 的搜索没有找到解决这个特定问题的任何结果。

我还没有尝试过这个(甚至没有编译过),但你可以看看使用可变辅助方法:

+ (NSString *)keyPathFromSelectors:(SEL)firstArg, ...
{
    NSMutableArray *keys = [NSMutableArray array];

    va_list args;
    va_start(args, firstArg);

    for (SEL arg = firstArg; arg != nil; arg = va_arg(args, SEL))
    {
        [keys addObject:NSStringFromSelector(arg)];
    }

    va_end(args);

    return [keys componentsJoinedByString:@"."];
}

我使用来自 libextobjc 的 EXTKeyPathCoding.h。您可以在 https://github.com/jspahrsummers/libextobjc/blob/master/extobjc/EXTKeyPathCoding.h

查看他们是如何做的

Swift 3 添加#keyPath()以从"property chain".

生成关键路径字符串
let keyPathString = #keyPath(MyType.myProperty1.myProperty2)

函数内的标记不是字符串,将由编译器检查。