当你拥有的只是代理对象时,有没有办法测试选择器/方法?
/* Proxy which may forward
* the method to some other object */
id proxy = [UINavigationBar appearance];
/* This condition returns FALSE
* despite the fact that the method would have otherwise been
* successfully executed at its destination */
if([proxy respondsToSelector:@selector(setBarTintColor:)]){
[proxy setBarTintColor:color];
}
答案 0 :(得分:2)
显然你不能。
其他答案建议的方法很容易破解,这是一个例子:
UINavigationBar
个实例会回应选择器setTranslucent:
setTranslucent:
未在标头文件UI_APPEARANCE_SELECTOR
因此以下代码
if([[UINavigationBar class] instancesRespondToSelector:@selector(setTranslucent:)]) {
[[UINavigationBar appearance] setTranslucent:NO]; // BUM!
}
会导致崩溃。
有关哪些选择器符合UIAppearance
的唯一信息似乎是UI_APPEARANCE_SELECTOR
宏,它在编译时被删除。
运行时检查看起来不可行。
为了完整起见,这是一种糟糕(但实用)的方式。
@try {
[[UINavigationBar appearance] setTranslucent:YES];
} @catch (NSException *exception) {
if ([exception.name isEqualToString:@"NSInvalidArgumentException"])
NSLog(@"Woops");
else
@throw;
}
然而,这非常脆弱,因为无法保证您只捕获选择器不符合UIAppearance
的情况。
答案 1 :(得分:1)
最好的选择似乎是
UI_APPEARANCE_SELECTOR
定义了相关媒体资源。在针对类UINavigationBar
本身的代码测试中,而不是其外观
if ([(some UINavigationBar object) respondsToSelector:@selector(setBarTintColor:)])...
或者,如另一个答案所示,
if ([UINavigationBar.class instancesRespondToSelector:@selector(setBarTintColor:)])...
虽然理论上proxy
是不同类的对象,但外观代理似乎是Apple自动从标记为UI_APPEARANCE_SELECTOR
的方法生成的。正如UIAppearance.h
中的评论所述:
要参与外观代理API,请使用
UI_APPEARANCE_SELECTOR
在标题中标记外观属性选择器。
如果您为旧版iOS中通过外观代理提供但后来从代理中删除的属性实现此方法,则此方法将中断。在同一个文件中记录了一个这样的例子:
在iOS7上......
tintColor
现在不允许使用外观代理。
因此,您需要测试极少数情况,以确保代码不会受到新iOS的破坏,但您仍然无需手动编写版本号。