1动态方法解析
如果一个对象调用了在这个类中方法列表中找不到选择子(SEL),这个时候可以使用为这个选择子添加一个方法
#import "ViewController.h"
#import <objc/runtime.h>
#import <objc/message.h>
@interface ViewController ()
@end
@implementation ViewController
void noParameterMethod (id self , SEL sel);
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self performSelector:@selector(method:) withObject:@"123"];
[self performSelector:@selector(noParameterMethod)];
}
void method (id self ,SEL sel ,id objc){
NSLog(@"%@",objc);
}
void noParameterMethod (id self , SEL sel){
NSLog(@"无参数的函数");
}
+(BOOL)resolveInstanceMethod:(SEL)sel{
NSLog(@"%@",NSStringFromSelector(sel));
if ([NSStringFromSelector(sel) hasPrefix:@"method"]) {
class_addMethod(self, sel, (IMP)method, "v@:@");
return YES;
}else if ([NSStringFromSelector(sel) hasPrefix:@"noParameterMethod"]){
class_addMethod(self, sel, (IMP)noParameterMethod, "v@:");
return YES;
}else{
return [super resolveInstanceMethod:sel];
}
}
@end
打印信息为
备援接受者
可以把自己不能识别的选择子交给其他对象进行处理
[self performSelector:@selector(forwardSelecter)];
-(id)forwardingTargetForSelector:(SEL)aSelector{
NSString * selectorString = NSStringFromSelector(aSelector);
if ([selectorString isEqualToString:@"forwardSelecter"]) {
SecondViewController * vc = [[SecondViewController alloc]init];
return vc;
}else{
return [super forwardingTargetForSelector:aSelector];
}
}
#import "SecondViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
-(void)forwardSelecter{
NSLog(@"备源消息转发");
}
完整的消息转发
[self performSelector:@selector(normalForwardSelector)];
[self performSelector:@selector(normalForwardPaSelector:) withObject:@"带有参数456"];
-(void)forwardInvocation:(NSInvocation *)anInvocation{
SEL sel = anInvocation.selector;
SecondViewController * vc = [[SecondViewController alloc]init];
if ([vc respondsToSelector:sel]) {
[anInvocation invokeWithTarget:vc];
}else{
[self doesNotRecognizeSelector:sel];
}
}
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSMethodSignature * signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
signature = [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return signature;
}
#import "SecondViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
-(void)forwardSelecter{
NSLog(@"备源消息转发");
}
-(void)normalForwardSelector{
NSLog(@"完整的消息转发");
}
-(void)normalForwardPaSelector:(NSString *)objc{
NSLog(@"%@",objc);
}
@end
Objective-C 中给一个对象发送消息会经过以下几个步骤:
在对象类的 dispatch table 中尝试找到该消息。如果找到了,跳到相应的函数IMP去执行实现代码;
如果没有找到,Runtime 会发送 +resolveInstanceMethod:
或者 +resolveClassMethod:
尝试去 resolve 这个消息;
如果 resolve 方法返回 NO,Runtime 就发送-forwardingTargetForSelector:
允许你把这个消息转发给另一个对象;
如果没有新的目标对象返回, Runtime 就会发送-methodSignatureForSelector:
和 -forwardInvocation:
消息。你可以发送 -invokeWithTarget:
消息来手动转发消息或者发送 -doesNotRecognizeSelector:
抛出异常。
网友评论