美文网首页
runtime总结

runtime总结

作者: 细雨菲菲v | 来源:发表于2018-07-11 15:28 被阅读22次
截图19.png

1.数据结构

(1)objc_object
截图1.png
(2)objc_class
截图2.png
(3)isa指针
截图3.png
什么是isa指针?isa分为指针型isa,isa的值代表class地址,非指针型isa的值的部分代表class的地址。
(4)isa指向
  • 关于对象,其指向类对象
    截图4.png
  • 关于类对象,其指向元类对象
    截图5.png
(5) catch_t
  • 用于快速查找方法执行的函数。
  • 可增量扩展哈希表结构
  • 局部性原理的最佳应用
    数据结构如下图
    截图6.png
(6) class_data_bits_t
  • class_data_bits_t主要是对class_rw_t的封装
  • class_rw_t代表了类相关的读写信息,对class_ro_t的封装
(7) class_rw_t
截图7.png
(8) class_ro_t
截图8.png
(9) method_t
截图9.png
Type Encodings
  • const char * types
    截图10.png
    整体数据结构
    图11.png

2.对象、类对象、元类对象

  • 类对象存储实例方法列表等信息
  • 元类对象存储类方法列表等信息
    截图12.png
    类对象和元类对象之间有什么区别和联系?
    实例对象可以通过isa指针找到类对象,从而找到类对象中存储的实例方法列表等信息,类对 象可以通过isa指针找到元类对象,从而找到元类对象中存储的类方法列表等信息,类对象和元类对象都是objc_class这种数据结构的。对于任何一个元类对象,它的isa指针都指向根元类对象。根元类对象的superClass指针指向根类对象。
    思考
    调用一个类方法,会沿着元类对象及其元类对象的父类的方法列表依次查找,当类方法在元类对象中找不到时,就会找根类对象中,同名的实例方法实现。
    消息传递过程
    调用实例方法, 首先系统会根据当前实例的isa指针,找到对应的类对象,在类对象及其父类的方法列表中依次查找,直到找到根类对象,如果还是没用找到,就会走到消息的转发流程。
    调用类方法,系统会根据当前类的isa指针,找到对应的元类对象,在元类对象及其元类对象的父类方法列表中依次查找,直到找到根元类,如果根元类中也没有,就会到根类对象中查找同名的实例方法,如果最终还是没找到就会走到消息的转发流程。

3.消息传递

图13.png
14.png
截图15.png
#import "Phone.h"
@implementation Phone
- (instancetype)init{
    self = [super init];
    if (self) {
        NSLog(@"%@",NSStringFromClass([self class]));
        NSLog(@"%@",NSStringFromClass([super class]));
    }
    return self;
}
@end
最终的打印结构是一致的,都是Phone 
(1)缓存查找

给定值SEL,目标值是对应bucket_t中的IMP

截图16.png
首先根据方法选择器,通过一个函数映射出bucket_t在数组中的位置,这一步骤涉及到哈希查找。哈希查找就是根据给定的一个值,然后经过哈希函数的算法算出的值,就是给定的值的在数组中的索引位置。
(2)当前类中查找
  • 对于已排序好的列表,采用二分查找算法查找方法对应执行函数。
  • 对于没有排序的列表,采用一般遍历查找方法对应执行函数。

(3)父类逐级查找


截图17.png

4.消息转发

截图19.png

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    RuntimeObject *obj = [[RuntimeObject alloc] init];
    [obj test];
    return YES;
}

#import <Foundation/Foundation.h>
@interface RuntimeObject : NSObject
- (void)test;
@end

#import "RuntimeObject.h"
@implementation RuntimeObject
+ (BOOL)resolveInstanceMethod:(SEL)sel{
    //如果test方法 打印日志
    if (sel == @selector(test)) {
        NSLog(@"resolveInstanceMethod:");
        return NO;
    }else{
        return [super resolveInstanceMethod:sel];
    }
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"forwardingTargetForSelector");
    return nil;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    if (aSelector == @selector(test)) {
        NSLog(@"methodSignatureForSelector");
        // v代表返回值是void类型   @代表第一个参数类型是id,即self
        // : 代表第二个参数是SEL类型的,即@selector(test) 
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }else{
        return [super methodSignatureForSelector:aSelector];
    }
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    NSLog(@"forwardInvocation");
}

打印结果:


截图.png

5.Method-Swizzling

截图20.png
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    RuntimeObject *obj = [[RuntimeObject alloc] init];
    [obj test];
    return YES;
}

#import <Foundation/Foundation.h>
@interface RuntimeObject : NSObject

- (void)test;
- (void)otherTest;

@end

#import "RuntimeObject.h"
#import <objc/runtime.h>
@implementation RuntimeObject
+ (void)load{
     //获取test方法
     Method test = class_getInstanceMethod(self, @selector(test));
     //获取otherTest
     Method otherTest = class_getInstanceMethod(self, @selector(otherTest));
     //交换两个方法的实现
     method_exchangeImplementations(test, otherTest);
    
}
- (void)test{
    NSLog(@"test");
}
- (void)otherTest{
    //实际上调用test的具体实现
    [self otherTest];
    NSLog(@"otherTest");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{  
    //如果test方法 打印日志
    if (sel == @selector(test)) {
        NSLog(@"resolveInstanceMethod:");
        return NO;
    }else{
        return [super resolveInstanceMethod:sel];
    }
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"forwardingTargetForSelector");
    return nil;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    if (aSelector == @selector(test)) {
        NSLog(@"methodSignatureForSelector");
        // v代表返回值是void类型   @代表第一个参数类型是id,即self
        // : 代表第二个参数是SEL类型的,即@selector(test) 
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }else{
        return [super methodSignatureForSelector:aSelector];
    }
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    NSLog(@"forwardInvocation");
}
@end

打印结果


截图21.png

6.动态添加方法

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    RuntimeObject *obj = [[RuntimeObject alloc] init];
    [obj test];
    return YES;
}

#import <Foundation/Foundation.h>
@interface RuntimeObject : NSObject
- (void)test;
@end

#import "RuntimeObject.h"
#import <objc/runtime.h>
@implementation RuntimeObject
void testImp(void)
{
    NSLog(@"test invoke");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
     //如果test方法 打印日志
    if (sel == @selector(test)) {
        NSLog(@"resolveInstanceMethod:");
        class_addMethod(self, @selector(test),testImp,"v@:");
        return YES;
    }else{
        return [super resolveInstanceMethod:sel];
    }
}

打印结果


截图19.png

相关文章

网友评论

      本文标题:runtime总结

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