使用另一个 class 的选择器以编程方式构建 属性 路径。这是如何运作的?
Bulding property paths programatically with another class's selectors. How does this work?
我有一个方法 I,它采用可变数量的 @selector()
值和 returns 我不久前在此站点上找到的正确 NSString。这在为我构建 属性 路径时很有用,因为我不喜欢为此使用字符串的想法,并且喜欢编译器能够检查构建路径的值的想法。方法是:
+(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:@"."];
}
效果很好,但问题是:为什么?如果我在名为 person
的当前对象上有 属性 并且它有一个 name
路径显然是 person.name
并且对我的方法的调用看起来像:
+(NSSet *)keyPathsForValuesAffectingFoo
{
return [NSSet setWithObject:[self keyPathFromSelectors:@selector(person), @selector(name),nil]];
}
name
选择器在技术上(不应该)在我当前的 class 中可见,它在我有参考的 Person
class 中,所以如何我访问了正确的 name
SEL 对象?
选择器不保证该方法实际存在于相关对象上。您可能会收到编译器警告,指出选择器名称在任何地方都不存在,但您无法保证它确实存在于将要使用的对象上。例如,这个编译:
[person performSelector: @selector(applicationDidBecomeActive:)]
即使 applicationDidBecomeActive
存在于您的应用委托中而不是 person
。
但是!这种事情是可以通过编译器宏实现的。查看 libextobjc 库,它提供了您正在寻找的那种 selector/key 路径编译时检查。这就是 ReactiveCocoa 中许多关键路径魔法的强大动力,但它也可以独立使用。
我有一个方法 I,它采用可变数量的 @selector()
值和 returns 我不久前在此站点上找到的正确 NSString。这在为我构建 属性 路径时很有用,因为我不喜欢为此使用字符串的想法,并且喜欢编译器能够检查构建路径的值的想法。方法是:
+(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:@"."];
}
效果很好,但问题是:为什么?如果我在名为 person
的当前对象上有 属性 并且它有一个 name
路径显然是 person.name
并且对我的方法的调用看起来像:
+(NSSet *)keyPathsForValuesAffectingFoo
{
return [NSSet setWithObject:[self keyPathFromSelectors:@selector(person), @selector(name),nil]];
}
name
选择器在技术上(不应该)在我当前的 class 中可见,它在我有参考的 Person
class 中,所以如何我访问了正确的 name
SEL 对象?
选择器不保证该方法实际存在于相关对象上。您可能会收到编译器警告,指出选择器名称在任何地方都不存在,但您无法保证它确实存在于将要使用的对象上。例如,这个编译:
[person performSelector: @selector(applicationDidBecomeActive:)]
即使 applicationDidBecomeActive
存在于您的应用委托中而不是 person
。
但是!这种事情是可以通过编译器宏实现的。查看 libextobjc 库,它提供了您正在寻找的那种 selector/key 路径编译时检查。这就是 ReactiveCocoa 中许多关键路径魔法的强大动力,但它也可以独立使用。