美文网首页
iOS设计模式 (八) 代理模式消息机制

iOS设计模式 (八) 代理模式消息机制

作者: handsome5 | 来源:发表于2018-05-12 18:26 被阅读17次
    消息机制
    7.png
    • 上图我们可以看出iOS消息机制是分三步, 动态方法解析,消息转发重定向,生成方法签名以及方法的签名派发来实现,下面看具体demo
    • Person (Person.m类没有实现方法)
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    
    - (void)run;
    
    @end
    
    
    • Car类
    #import <Foundation/Foundation.h>
    
    @interface Car : NSObject
    
    //- (void)carRun;
    
    @end
    
    #import "Car.h"
    
    @implementation Car
    
    - (void)run
    { 
        NSLog(@"车=====:%@",@"跑起来了");
    }
    
    @end
    
    • ViewController类
    #import "ViewController.h"
    #import "Person.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        Person *p = [Person new];
        [p run];
    }
    @end
    
    • 运行demo,[p run]没有实现引发崩溃 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person run]: unrecognized selector sent to instance 0x60400000f3a0',
      *** First throw call stack:;

    追踪下[p run]是崩溃的步骤

    一.动态方法解析
    + BOOL)resolveClassMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
    + (BOOL)resolveInstanceMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
    
    二.消息转发重定向
    - (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
    
    三.生成方法签名
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");
    
    四.方法的签名派发
    - (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE("");
    
    • 上面一,二都能单独处理崩溃,三,四合在一起也是能处理,看看是如何用runtime来消息机制
    • 动态方法解析来实现添加run方法
    /**
     动态方法解析
     @param sel selector
     @return yes or no
     */
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        //1.判断没实现方法, 就动态添加方法
        if (sel == @selector(run)) {
            // 动态添加方法  IMP(函数指针)
            class_addMethod(self, sel, (IMP)runValue, "v@:");
            return YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    
    void runValue(id self , SEL sel)
    {
        //id self , SEL sel
    }
    
    • 动态方法解析返回NO的话就会走到消息重定向,我们把动态解析的动态添加方法给注释调让它返回NO
    /**
     动态方法解析
     @param sel selector
     @return yes or no
     */
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        
    //    //1.判断没实现方法, 就动态添加方法
    //    if (sel == @selector(run)) {
    //        // 动态添加方法  IMP(函数指针)
    //        class_addMethod(self, sel, (IMP)runValue, "v@:");
    //        return YES;
    //    }
        return [super resolveInstanceMethod:sel];
    }
    
    void runValue(id self , SEL sel)
    {
        //id self , SEL sel
    }
    
    //二.消息转发重定向
    - (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0){
        
        NSLog(@"aSelector ===== :%@",NSStringFromSelector(aSelector));
       // return [Car new];
        return [super forwardingTargetForSelector:aSelector];
    }
    
    • 注意这里的如果返回return [Car new];如果我们在Car 类方法里面找到 run这个方法,程序会崩溃么?找不到run方法的话又怎样呢?如果没找到的话,return [super forwardingTargetForSelector:aSelector];会怎样呢?
    • 接下来看下生成的方法签名以及签名派发
    //三.生成方法签名
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("")
    {
        // return [super methodSignatureForSelector:aSelector];
         NSString *selector =  NSStringFromSelector(aSelector);
        if ([selector isEqualToString:@"run"]){
            NSLog(@"实现run方法");
        }
        //(const char *)types;
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
     
    }
    
    // 四.方法的签名配发
    - (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE(""){
        
        NSLog(@"----%@----",anInvocation);
        //1.拿到消息
        SEL selector = [anInvocation selector];
    
        //转发消息
        Car *car = [Car new];
        if ([car respondsToSelector:selector]){
            // 调用这个对象, 去进行转发
            [anInvocation invokeWithTarget:car];
        }
        else {
            /**
             这里抛异常
             */
            [super forwardInvocation:anInvocation];
        }
    }
    
    • 控制台输出 8.png

    相关文章

      网友评论

          本文标题:iOS设计模式 (八) 代理模式消息机制

          本文链接:https://www.haomeiwen.com/subject/ohbukftx.html