方法查找,传递
一:调用未实现的方法(只有声明),会出现崩溃
MethodForwardTest *methodForward = [[MethodForwardTest alloc] init];
[methodForward test]; // test 方法只有定义没有实现,需要进行消息转发
崩溃信息如下:
2017-02-09 10:30:38.096 runtime[9274:686763] -[MethodForwardTest test]: unrecognized
selector sent to instance 0x100b00700
二:其实在崩溃之前会有三次机会进行弥补,三次机会如下,调用顺序也如下所示:
/**
* 第一次机会,动态添加方法
*/
id dynamicMethod(id self, SEL _cmd) {
NSLog(@"首先尝试动态添加方法");
return @"首先尝试动态添加方法";
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSString *selectorString = NSStringFromSelector(sel);
if ([selectorString isEqualToString:@"test"]) {
class_addMethod(self, sel, (IMP)dynamicMethod, "@@:");
}
return YES;
}
/**
* 第二次机会,方法转发
*
* @param sel 需要处理的方法
*
* @return 能够处理这个方法的对象
*/
- (id)forwardingTargetForSelector:(SEL)aSelector {
return [[Replacement alloc] init];
}
/**
* 第三次机会,完整的方法转发
*/
- (void)anotherTest {
NSLog(@"另一个test方法");
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
if (!signature) { // 如果不能处理这个方法
if ([self respondsToSelector:@selector(anotherTest)]) {
// 返回另一个函数的方法签名,这个函数不一定要定义在本类中
signature = [MethodForwardTest instanceMethodSignatureForSelector:@selector(anotherTest)];
}
}
return signature;
}
方法交换
一:可以对方法进行交换
一般把方法交换的实现写在load方法中,不过这里为方便对比交换前后的效果,没有将实现过程写在load里面
- (void)test {
NSLog(@"未进行Method Swizzling之前:");
// 小写的
NSLog(@"小写字符串:%@", [mixedString lowercaseString]);
[self startMethodSwizzling];
NSLog(@"进行Method Swizzling之后:");
NSLog(@"小写字符串:%@", [mixedString lowercaseString]);
}
- (void)startMethodSwizzling {
Method originalLowercaseStringMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
Method newLowercaseStringMethod = class_getInstanceMethod([NSString class], @selector(myLowercaseString));
method_exchangeImplementations(originalLowercaseStringMethod, newLowercaseStringMethod);
}
二:这里着重要介绍一下class_getInstanceMethod方法的相关参数的意义

OBJC_EXPORT Method class_getInstanceMethod(Class cls, SEL name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);
Returns a specified instance method for a given class.
Note that this function searches superclasses for implementations, whereas
class_copyMethodList does not
此方法的描述:
返回一个指定的特定类的实例方法。注意,这个函数搜索父类的实现,而与class_copyMethodList(//获得该类中所有的方法,属性的set,get方法也包涵在内,还有一个 .cxx_destruct的方法-也就是delloc方法,不会去其父类中查找)这个方法的作用不同
parameter:
Class cos:The class you want to inspect
SEL name:The selector of the method you want to retrieve.
参数1:你想要检查的类
参数2:你想要检索的方法
returns:The method that corresponds to the implementation of the selector
specified by aSelector for the class specified by aClass, or NULL if the
specified class or its superclasses do not contain an instance method with the
specified selector
返回值:返回一个方法类的值,这个值是指定的类,或者指定的类的父类包含的实例
方法,如果指定的类以及其父类中都包含这样的方法,那么返回NULL
网友评论