runtime

iOS消息转发

2018-06-06  本文已影响47人  孔凡伍

title: “iOS消息转发”
date: 2016-03-22 13:48:38
tags:


消息转发这块,我学习了三次。2次看书,1次看博客。每次看的都很明白。但是由于开发中使用很少,好忘。所以这里记录下。方便日后查看。

消息转发我分2个阶段。

一 这个消息由自己(本类)来响应阶段。
  1. 当向一个A类发送未实现的消息时。A类会调用 + (BOOL)resolveInstanceMethod:(SEL)sel 这个方法,动态的添加一个Method来响应。(添加Method看下边代码)
二 由其他类来响应阶段。
  1. 当 + (BOOL)resolveInstanceMethod:(SEL)sel 方法返回NO,就会调用 - (id)forwardingTargetForSelector:(SEL)aSelector 方法,询问是否交给其他类响应此消息。(添加看下边代码)
  2. 如果 - (id)forwardingTargetForSelector:(SEL)aSelector 返回nil,调用 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 先进行方法签名,再调用 - (void)forwardInvocation:(NSInvocation *)anInvocation 方法进行转发。

图片来自 http://www.cocoachina.com/ios/20151208/14595.html

Resize icon

void run (id self, SEL _cmd)
{
    NSLog(@"%@ %s", self, sel_getName(_cmd));
}

+ (BOOL)resolveInstanceMethod:(SEL)sel
{
//    if (sel == @selector(run)) {
//        class_addMethod(self, sel, (IMP)run, "v@:");
//        return YES;
//    }
    return [super resolveInstanceMethod:sel];
}


- (id)forwardingTargetForSelector:(SEL)aSelector
{
//    if (aSelector == @selector(run)) {
//        return FWCar.new;
//    }
    return [super forwardingTargetForSelector:aSelector];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSString *sel = NSStringFromSelector(aSelector);
    if ([sel isEqualToString:@"run"]) {
        // 为转发方法手动生成签名
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    SEL sel = anInvocation.selector;
    FWCar *car = FWCar.new;
    if ([car respondsToSelector:sel]) {
        // 唤醒这个方法
        [anInvocation invokeWithTarget:car];
    }
}
上一篇下一篇

猜你喜欢

热点阅读