简而言之,下面的代码调用超类中的现有选择器,然后给出NSInvalidException:
- (void)applicationWillResignActive:(UIApplication *)application {
if ([super respondsToSelector:@selector(applicationWillResignActive:)])
{
[super applicationWillResignActive:application];
}
这给出了以下日志异常:
详细说明......我有一个基础应用程序委托(来自我们的新公司库)声明为:
我有一个基本应用程序委托类BaseAppDelegate。它被声明为:
@interface CoAppDelegate : NSObject <UIApplicationDelegate>
它实现:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
DebugLog(@"*** ACTIVE ****");
}
它没有实现@selector(applicationWillResignActive :) - 或者至少我的意思是我没有专门为该方法编写代码。它在.h或.m文件中找不到。
我的应用程序有一个应用程序委托,它继承自CoAppDelegate:
@interface aAppDelegate : CoAppDelegate <UIApplicationDelegate>
我将以上两种方法实现为:
- (void)applicationWillResignActive:(UIApplication *)application {
if ([super respondsToSelector:@selector(applicationWillResignActive:)])
{
[super applicationWillResignActive:application];
}
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
if ([super respondsToSelector:@selector(applicationDidBecomeActive:)])
{
[super applicationDidBecomeActive:application];
}
}
当应用程序启动时,我得到调试输出“*** ACTIVE ****” - 应该这样。
当我将我的应用程序发送到后台时,我得到NSInvalidArgumentException,指出响应者不存在 - 并且它不存在,所以这是正确的抛出异常。
我需要知道的是,为什么当我期待看到NO时,responseToSelector会给出YES?我错过了什么微妙的东西?
答案 0 :(得分:9)
出于instancesRespondToSelector:
:
通过使用
respondsToSelector:
关键字将super
发送到对象,您无法测试对象是否从其超类继承方法。这个方法仍然会测试整个对象,而不仅仅是超类的实现。因此,将
respondsToSelector:
发送到super
相当于将其发送到self
。相反,您必须直接在对象的超类上调用NSObject
类方法instancesRespondToSelector:
。
您的子类'代码应如下所示:
- (void)applicationWillResignActive:(UIApplication *)application {
if ([[self superclass] instancesRespondToSelector:_cmd])
{
[super applicationWillResignActive:application];
}
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
if ([[self superclass] instancesRespondToSelector:_cmd])
{
[super applicationDidBecomeActive:application];
}
}
答案 1 :(得分:9)
而不是[super class]
,您应该使用[self superclass]
:
[[self superclass] instancesRespondToSelector:@selector(method)]
答案 2 :(得分:0)
[[self superclass] instancesRespondToSelector:<selector>];
在某些特殊情况下,可能会产生不良结果。最好明确说明类名而不是self:
[[<ClassName> superclass] instancesRespondToSelector:<selector>];
<强>解释强>
考虑例子:
@protocol MyProtocol <NSObject>
@optional
- (void)foo;
- (void)bar;
@end
@interface A : NSObject <MyProtocol>
@end
@implementation A
- (void)foo {
//Do sth
}
@end
@interface B : A
@end
@implementation B
- (void)bar {
//B may not know which methods of MyProtocol A implements, so it checks
if ([[self superclass] instancesRespondToSelector:@selector(bar)]) {
[super bar];
}
//Do sth
}
@end
@interface C : B
@end
@implementation C
@end
想象一下接下来的代码:
C *c = [C new];
[c bar];
这段代码......崩溃了!为什么?让我们深入研究在C实例上调用bar方法时所发生的事情&#39; c&#39;。 [self superclass]返回... B,因为self是C的实例。当然,B实例响应bar,所以输入if的主体。但是,[超级栏]尝试从B的角度调用超级实现,所以尝试在A上调用bar,这会导致崩溃!
这就是为什么我建议用精确的[B超类]替换[self superclass] - 这解决了问题。