设为首页 加入收藏

TOP

iOS runtime的理解和应用(一)
2017-10-13 10:23:40 】 浏览:4315
Tags:iOS runtime 理解 应用

项目中经常会有一些的功能模块用到runtime,最近也在学习它.对于要不要阅读runtime的源码,我觉得仅仅是处理正常的开发,那真的没有必要,只要把常用的一些函数看下和原理理解下就可以了.
但是如果真能静下心好好阅读源码,真的能帮你更加深入理解objc本身以及经过高阶包装出来的那些特性。

什么是runtime

runtime就是运行时,每个语言都有它的runtime.通俗点讲就是程序运行时发生的事情.
比如C语言,在编译的时候就决定了调用哪些函数,通过编译后就一步步执行下去,没有任何二义性,所以它是静态语言.
而objc的函数调用则可以理解为发消息,在编译的时候完全不能决定哪个函数执行,只有在运行的时候才会根据函数名找到函数调用,所以在运行的时候它能动态地添加调换属性,函数.所以它是动态语言.
动态和静态语言没有明显的界限,我感觉它们就是以runtime来区分的,看它在runtime时,有多灵活,那么它就有多动态.

  • 相关定义

    typedef struct objc_method *Method
    struct objc_method {
    SEL method_name;            
    char *method_types;
    IMP method_imp;
    } 

    SEL是char*,可以理解为函数的姓名.
    IMP就是函数指针,指向函数的实现.
    ==在objc_class中method list保存了一个SEL<>IMP的映射.所以通过SEL可以找到函数的实现==

typedef struct objc_ivar *Ivar;
struct objc_ivar {
    char *ivar_name;
    char *ivar_type;
    int ivar_offset;
#ifdef __LP64__
    int space;
#endif
}                                                            

实例变量,跟某个对象关联,不能被静态方法使用,与之想对应的是类变量

typedef struct objc_category *Category;
struct objc_category {
    char *category_name;           
    char *class_name;
    struct objc_method_list *instance_methods;
    struct objc_method_list *class_methods;
    struct objc_protocol_list *protocols;
}      

Catagory可以动态地为已经存在的类添加新的行为。比如类方法,实例方法,协议.
==根据结构可知,不能添加属性,实例变量==

struct objc_method_list {
    struct objc_method_list *obsolete;
    int method_count;
    int space;
    struct objc_method method_list[1];
}  

struct objc_ivar_list {
    int ivar_count;
    int space;
    struct objc_ivar ivar_list[1];
}                                                                    

==简单地理解为存有方法和实例变量的数组==

//类在runtime中的表示
struct objc_class {
    Class isa;//指针,顾名思义,表示是一个什么,
              //实例的isa指向类对象,类对象的isa指向元类

#if !__OBJC2__
    Class super_class;  //指向父类
    const char *name;  //类名
    long version;
    long info;
    long instance_size
    struct objc_ivar_list *ivars //成员变量列表
    struct objc_method_list **methodLists; //方法列表
    struct objc_cache *cache;//缓存
    //一种优化,调用过的方法存入缓存列表,下次调用先找缓存
    struct objc_protocol_list *protocols //协议列表
    #endif
};

struct objc_cache {
    unsigned int mask;
    unsigned int occupied;
    Method buckets[1];
};

==objc_cache可以理解为存最近调用过的方法的数组,每次调用先访问它,提高效率==

runtime常用方法

  • 获取列表
    我们可以通过runtime的一系列方法获取类的一些信息(包括属性列表,方法列表,成员变量列表,和遵循的协议列表)

    class_copyPropertyList       //获取属性列表
    class_copyMethodList         //获取方法列表     
    class_copyIvarList           //获取成员变量列表
    class_copyProtocolList       //获取协议列表

    常见用于字典转模型的需求中:

@interface LYUser : NSObject
@property (nonatomic,strong)NSString *userId;
@property (nonatomic,strong)NSString *userName;
@property (nonatomic,strong)NSString *age;
@end

- (void)viewDidLoad {    
    [super viewDidLoad];    
    //利用runtime遍历一个类的全部成员变量
    NSDictionary *userDict = @{@"userId":@"1",@"userName":@"levi",@"age":@"20"};
    unsigned int count;
    LYUser *newUser = [LYUser new];
    objc_property_t *propertyList = class_copyPropertyList([LYUser class], &count);
    for (int i = 0; i < count; i++) {
        const char *propertyName = property_getName(propertyList[i]);
        NSString *key = [NSString stringWithUTF8String:propertyName];
        [newUser setValue:userDict[key] forKey:key];
    }
    NSLog(@"%@--%@--%@",newUser.userId,newUser.userName,newUser.age);     
}  

==这只是最简单的转化,还要考虑容错,转换效率,现在有很多开源框架做的很不错.这是一些开源框架的性能对比:==模型转换库评测结果

  • 交换方法
class_getInstanceMethod() //类方法和实例方法存在不同的地方,所以两个不同的方法获得
class_getClassMethod()    //以上两个函数传入返回Method类型
method_exchangeImplementations    //()交换两个方法的实现

==这个用到的地方很多,可以大大减少我们的代码量,常用的有防错措施,统计打点,统一

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇【改】iOS学习之NSAttributedStri.. 下一篇Quartz2D简介

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目