问题
I am trying to override a UIStoryboard method using a category. Here is my implementation:
#import "UIStoryboard+SomeCategory.h"
#import <UIKit/UIKit.h>
@implementation UIStoryboard(SomeCategory)
-(id)instantiateInitialViewController
{
NSLog(@"SUPER CLASS: %@", [super class]); // logs "UIStoryboard"
NSLog(@"SUPER RTS : %@", [super respondsToSelector:@selector(instantiateInitialViewController)] ? @"YES" : @"NO"); // logs "YES"
return [super instantiateInitialViewController];
}
@end
when I add:
UIViewController *viewController = [super instantiateInitialViewController]
Why do I get the compiler error:
Receiver type 'NSObject' for instance message does not declare a method with selector 'instantiateViewController'
回答1:
You should note that [super class]
is not the same as [self superclass]
. Quoting the docs:
Objective-C provides two terms that can be used within a method definition to refer to the object that performs the method—self and super.
They differ in how the compiler will search for the method implementation, and in some cases they will mean just the same.
In this case you want:
NSLog(@"SUPER CLASS: %@", [self superclass]); // logs "NSObject"
to check an object's super class class, and you'll need a UIStoryBoard subclass, not a category, to be able to use:
return [super instantiateInitialViewController];
Why [super class]
doesn't log what you expect is another subject. If you're interested, this post What is a meta-class in Objective-C? is a good starting point.
回答2:
If you use super
when overriding methods using a category, the method will be called on the superclass of the object, not the object you are overriding the method on. You haven't made a subclass of UIStoryboard
, so super
refers to NSObject
- which is reflected accurately in your error message.
I don't know what's going on with your log messages, though.
Using a category to override a method means that you can't call the original method. You'll need to either make a subclass of UIStoryboard
or an entirely new method in the category, that calls [self instantiateInitialViewController]
.
回答3:
You need to use method swizzling. good explanation of how to use it for your purposes here: http://b2cloud.com.au/how-to-guides/method-swizzling-to-override-in-a-category
回答4:
If you really want to call that method from a UIViewController, your category should be:
@implementation UIViewController(SomeCategory)
Even so, it would call the super of your UIViewController, so it would still not work. You also need to do the following:
UIViewController *viewController = [self instantiateInitialViewController]
来源:https://stackoverflow.com/questions/7891822/selector-sent-to-method-overridden-in-category-fails