OC中調(diào)用方法就是向?qū)ο蟀l(fā)送消息
下面的代碼:
[self performSelector:@selector(method) withObject:nil];
如果說method方法不存在,就會出現(xiàn):unrecognized selector sent to instance
從發(fā)送消息到崩潰中間經(jīng)歷了什么?
首先分兩種情況
1,如果發(fā)送的是一個實例方法,會經(jīng)過三個步驟
第一步:
+ (BOOL)resolveInstanceMethod:(SEL)sel
這個方法是實例方法未實現(xiàn)時自動執(zhí)行,這個方法里面是讓你在當(dāng)前類里面對未實行的方法做彌補
void dynamicMethodIMP(id sel,SEL _cmdd){
NSLog(@"resolveInstanceMethod調(diào)用成功");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(method)) {
// class_addMethod([self class],sel,(IMP));
class_addMethod([self class],sel,(IMP)dynamicMethodIMP, "v@:");
return YES;
}
return [super resolveInstanceMethod:sel];
}
第二步:
如果第一步resolveInstanceMethod你沒做處理,便會來到這一步,如果你處理了第一步,第二步是不會執(zhí)行的
- (id)forwardingTargetForSelector:(SEL)aSelector{
if (aSelector == @selector(method)) {
return [TestClass new];
}
return nil;
}
@implementation TestClass
- (void)method{
NSLog(@"method");
}
@end
這一步是在其他類里面找對應(yīng)的方法,所以TestClass里面必須要實現(xiàn)method方法,不然同樣會崩潰
第三步:
經(jīng)歷過第一步,在本類中找彌補方法,第二步,在其他類中找彌補方法后,如果都沒有找到,便會來到第三步
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
if (!methodSignature) {
methodSignature = [NSMethodSignature signatureWithObjCTypes:"v@:*"];
}
return methodSignature;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
testClass *messageForwarding = [testClass new];
if ([messageForwarding respondsToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:messageForwarding];
}
}
這一步實現(xiàn)方法的重新簽名
2.如果是調(diào)用了一個類方法,該類方法沒有實現(xiàn)該怎么辦
便會調(diào)用resolveClassMethod
void dynamicMethodIMP(id sel,SEL _cmdd){
NSLog(@"resolveInstanceMethod調(diào)用成功");
}
@implementation testObject
+ (BOOL)resolveClassMethod:(SEL)sel{
if (sel == @selector(hehe1)){
class_addMethod(objc_getMetaClass("testObject"),sel,(IMP)dynamicMethodIMP, "v@:");
return YES;
}
return [super resolveInstanceMethod:sel];
}
@end
看里面class_addMethod的第一個參數(shù),是objc_getMetaClass("testObject"),該方法是獲取當(dāng)前類的元類,如果用[self class]是會崩潰的,因為dynamicMethodIMP是一個c方法,它是存在于元類里面的MessageList里面的,當(dāng)前類找不到該方法,元類的知識可以看我另一篇文章:iOS類和元類關(guān)系
如果resolveClassMethod方法沒有實現(xiàn),就會直接崩潰,也就是說它沒有實例方法里面的第二步和第三步。
resolveInstanceMethod和methodSignatureForSelector、forwardInvocation只是在實例方法缺失才會執(zhí)行,類方法缺失不會執(zhí)行,這點要注意