iOS消息转发

作者: 小罗哦吧 | 来源:发表于2019-02-20 15:41 被阅读0次

    1.在说消息转发前需要先理解objc_magsent, objc_msgSend函数会依据接收者与选择子(SEL)的类型来调整适当的方法。为了完成此操作,该方法需要在接收者所属的类中搜寻其“方法列表”如果能找到与选择子名称相符的方法,就调整至其代码,如果找不到,就沿着继承体系继续向上查找,等找到合适的方法之后在跳转,如果还是找不到相符合的方法那就执行消息转发

    2.上面是消息转发的条件消息转发包括一下:

    1.动态方法解析(+ (BOOL)resolveInstanceMethod:(SEL)selector)他的作用是 类是否新增实力方法处理选择子有返回yes没有No

    2.备用接收者 (- (id)forwardingTargetForSelector:(SEL)aSelector) 如果1返回类NO就到2,2的作用是把消息转给其他接收者来处理消息 没有就返回nil

    3.完整消息转发 (-(void)forwardInvocation:(NSInvocation *)anInvocation) 如果2返回nil 创建NSInvocation 对象 封装全部细节 消息派发系统把消息派给目标对象

    举个例子 模拟下字典 为属性添加set get 方法

    @interface EOCAutoDictionary : NSObject
    @property(nonatomic,strong) NSString *string;
    @property(nonatomic,strong) NSNumber *number;
    @property(nonatomic,strong) NSDate *date;
    @property(nonatomic,strong) id opaqueObject;
    @end
    
    #import "EOCAutoDictionary.h"
    #import <objc/runtime.h>
    @interface EOCAutoDictionary()
    @property(nonatomic,strong) NSMutableDictionary *backingStore;
    @end
    @implementation EOCAutoDictionary
    @dynamic string,number,date,opaqueObject;//这个是让用户自己实现get set 方法 
    - (id)init{
        if (self = [super init]) {
            _backingStore = [NSMutableDictionary new];
        }
        return self;
    }
    + (BOOL)resolveInstanceMethod:(SEL)selector{
        NSString *selectorString = NSStringFromSelector(selector);
        if ([selectorString hasPrefix:@"set"]) {
            class_addMethod(self,
                            selector,
                            (IMP)autoDictionarySetter,
                            "v@:@");
        }else{
            class_addMethod(self,
                            selector,
                            (IMP)autoDictionaryGetter,
                            "@@:");
        }
        
        return YES;
        
    }
    
    id autoDictionaryGetter(id self ,SEL _cmd){
        EOCAutoDictionary *typedSelf = (EOCAutoDictionary *)self;
        NSMutableDictionary *backingStore = typedSelf.backingStore;
        NSString *key = NSStringFromSelector(_cmd);
        return [backingStore objectForKey:key];
    }
    void autoDictionarySetter(id self ,SEL _cmd,id value){
         EOCAutoDictionary *typedSelf = (EOCAutoDictionary *)self;
         NSMutableDictionary *backingStore = typedSelf.backingStore;
        NSString *selectorString = NSStringFromSelector(_cmd);
        NSMutableString *key = [selectorString mutableCopy];
        [key deleteCharactersInRange:NSMakeRange(key.length-1, 1)];
        [key deleteCharactersInRange:NSMakeRange(0, 3)];
        NSString *lowercaseFirstChar = [[key substringToIndex:1] lowercaseString];
        [key replaceCharactersInRange:NSMakeRange(0, 1) withString:lowercaseFirstChar];
        if (value) {
            [backingStore setObject:value forKey:key];
        }else{
            [backingStore removeObjectForKey:key];
        }
        
    }
    

    外面调用

     EOCAutoDictionary *dict = [EOCAutoDictionary new];
        dict.date = [NSDate dateWithTimeIntervalSince1970:475372800];
        NSLog(@"date = %@",dict.date);
    

    相关文章

      网友评论

        本文标题:iOS消息转发

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