运行时
- (void)noReturnNoParams {
NSLog(@"noReturnNoParams");
}
- (NSString *)hasReturnHasParams:(NSString *)params {
NSLog(@"hasReturnHasParams:%@",params);
return params;
}
调用
// 一般调用
[self noReturnNoParams];
[self hasReturnHasParams:@"params"];
// 通过objc_msgSend调用
((void(*)(id,SEL))objc_msgSend)(self,@selector(noReturnNoParams));
((NSString *(*)(id,SEL,NSString *))objc_msgSend)(self,@selector(hasReturnHasParams:),@"this is param");
// 通过函数地址调用
void (*setter)(id,SEL);
setter = (void(*)(id, SEL, BOOL))[self methodForSelector:@selector(noReturnNoParams)];
setter(self, @selector(noReturnNoParams));
消息转发
通过 obj_msgSend 调用,在找不到imp的时候,就会进入消息转发流程
-
调用 + (BOOL)resolveInstanceMethod:(SEL)sel; 如果重写这个方法,动态添加未实现的方法,转发流程结束。
+ (BOOL)resolveInstanceMethod:(SEL)sel { NSLog(@"resolveInstanceMethod"); if (sel == @selector(nofunction)) { IMP imp = imp_implementationWithBlock(^{ NSLog(@"既然没有实现,那就动态添加方法"); }); class_addMethod([ObjcMsgSendVC class], sel, imp, "v@:"); // return YES/NO不知道有什么作用,看起来没什么影响 return NO; } return [super resolveInstanceMethod:sel]; }
-
触发 - (id)forwardingTargetForSelector:(SEL)aSelector ;可以指定一个对象来相应这个方法,如果返回nil,则进入下一步
- (id)forwardingTargetForSelector:(SEL)aSelector { NSLog(@"forwardingTargetForSelector:"); if (aSelector == @selector(nofunction)) { // Obviously if you return self from this method, the code would just fall into an infinite loop. // 但是系统做了优化,返回self也没事,但是不建议这么做 return self.delegate; } else { return [super forwardingTargetForSelector:aSelector]; } }
-
正常转发,可以传递给多个对象
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSLog(@"methodSignatureForSelector:"); if (aSelector == @selector(nofunction)) { // return nil;就不会调用下一步forwardInvocation: return [self methodSignatureForSelector:@selector(showWithAnimated:)]; } else { return [super methodSignatureForSelector:aSelector]; } } - (void)forwardInvocation:(NSInvocation *)anInvocation { NSLog(@"forwardInvocation:"); if (anInvocation.selector == @selector(nofunction)) { NSLog(@"anInvocation.selector == @selector(nofunction)"); [self showWithAnimated:YES]; } else { [super forwardInvocation:anInvocation]; } }
添加方法
SEL selector = @selector(test);
IMP imp =imp_implementationWithBlock(^{
NSLog(@"这是方法实现");
});
Method method = class_getInstanceMethod([AddMethodVC class], selector);
class_addMethod([AddMethodVC class], selector, imp, method_getTypeEncoding(method));
方法交换
- (void)origin {
NSLog(@"originMethod");
}
- (void)swizzle {
NSLog(@"这是Swizzle方法实现");
}
- (void)swizzleMethod {
SEL originSel = @selector(origin);
SEL swizzleSel = @selector(swizzle);
Method originMethod = class_getInstanceMethod([SwizzleMethodVC class], originSel);
Method swizzleMethod = class_getInstanceMethod([SwizzleMethodVC class], swizzleSel);
// 确定方法存在就可以直接交换,否则可以考虑,如果方法不存在,可以先添加
BOOL didAddMethod = class_addMethod([SwizzleMethodVC class], originSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
if (didAddMethod) {
class_replaceMethod([SwizzleMethodVC class], swizzleSel, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
} else {
method_exchangeImplementations(originMethod, swizzleMethod);
}
}
方法替换
- (void)replaceMethod {
// Method method = class_getInstanceMethod([ReplaceMethodVC class], @selector(swizzle));
//
// class_replaceMethod([ReplaceMethodVC class], @selector(origin), method_getImplementation(method), method_getTypeEncoding(method));
Method method = class_getInstanceMethod([ReplaceMethodVC class], @selector(origin));
IMP imp = imp_implementationWithBlock(^{
NSLog(@"这是新的方法实现");
});
class_replaceMethod([ReplaceMethodVC class], @selector(origin), imp, method_getTypeEncoding(method));
}
- (void)origin {
NSLog(@"originMethod");
}
- (void)swizzle {
NSLog(@"这是Swizzle方法实现");
}
网友评论