美文网首页
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