美文网首页
Runtime知识点整理3

Runtime知识点整理3

作者: 化二缺 | 来源:发表于2020-05-25 08:44 被阅读0次

objc_msgSend

实现源码是汇编 为了效率
方法查找是用C++ 找到IMP 填充到当前对象里 然后 就返回到汇编

[person personTest];
objc_msgSend(person,@selector(personTest))
消息接受者(receiver): person
消息名称: personTest

  • objc_msgSend的执行流程可以分为3大阶段
  • 消息发送
  • 动态方法解析
  • 消息转发

最后如果找不到会报错:unrecognized selector sent to instance

消息发送阶段

消息发送.png

动态方法解析 阶段

平时开发的时候用不到 主要就是面试

#import "YZPerson3.h"
#import <objc/runtime.h>
@implementation YZPerson3
struct method_t {
    SEL sel ;
    char * types;
    IMP imp;
};

-(void)retryOther{
    NSLog(@"retryOther %s", __func__);
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    
    if(sel == @selector(persontest)){
     //获取其他方法
       // struct method_t * method = (struct method_t *)class_getInstanceMethod(self, @selector(retryOther));
        Method method = class_getInstanceMethod(self, @selector(retryOther));
        
        
        //动态添加方法
       // class_addMethod(self, sel, method->imp, method-> types);
        class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method));
    }
    
    return  YES;
    
}
@end
    YZPerson3 * person = [[YZPerson3 alloc]init];
    
    //必须在h文件写上名字 
    [person persontest];
c语言方式.png
动态方法解析 流程.png
image.png

消息转发 阶段

消息转发 阶段.png

代码示例

  • 这里是对象方法 如果要用到 类方法类似+test 需要用 + forwordInvocation:方法
@interface YZPerson4 : NSObject
-(void)test:(int)age;
@end

#import <objc/runtime.h>
@implementation YZPerson4
//这里有对应的+方法 因为底层是用receiver 直接调用的名字
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    
    if (aSelector == @selector(test:)) {
        return  [NSMethodSignature signatureWithObjCTypes:"v@:i"];
    }
    return  [super methodSignatureForSelector:aSelector];
}
//这里有对应的+方法 因为底层是用receiver 直接调用的名字
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    //参数顺序 receiver selector other arguments
    int age ;
    [anInvocation getArgument:&age atIndex:2];
    
    NSLog(@"age + 10 = %d",age + 10);
    
}
@end

NSInvocation 对象

  • NSInvocation 文件里有关于方法签名的 枚举
enum _NSObjCValueType {
    NSObjCNoType = 0,
    NSObjCVoidType = 'v',
    NSObjCCharType = 'c',
    NSObjCShortType = 's',
    NSObjCLongType = 'l',
    NSObjCLonglongType = 'q',
    NSObjCFloatType = 'f',
    NSObjCDoubleType = 'd',
    NSObjCBoolType = 'B',
    NSObjCSelectorType = ':',
    NSObjCObjectType = '@',
    NSObjCStructType = '{',
    NSObjCPointerType = '^',
    NSObjCStringType = '*',
    NSObjCArrayType = '[',
    NSObjCUnionType = '(',
    NSObjCBitfield = 'b'
} API_DEPRECATED("Not supported", macos(10.0,10.5), ios(2.0,2.0), watchos(2.0,2.0), tvos(9.0,9.0));

@dynamic

  • 告诉编译器不用自动生成getter 和setter 的实现,等到运行时再添加方法实现
  • 了解下算了

相关文章

网友评论

      本文标题:Runtime知识点整理3

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