当前位置: 代码迷 >> Iphone >> 初涉Runtime (1)
  详细解决方案

初涉Runtime (1)

热度:185   发布时间:2016-04-25 05:30:27.0
初涉Runtime (一)

Objective-C 是一门动态语言,有很多东西都是运行时才确定的。

比如这句代码首先声明testObject是一个NSString,然后创建了一个NSData对象,并且将这个对象的内存地址保存在test Object中。运行的时候textObject只想的就是一个NSData对象。

NSString *testObject = [[NSData alloc]]init];

Runtime,是一套运行机制。是拿C语言一套比较底层的API,里面于很多很好很强大的方法。我们平写的OC的代码转成Runtime进行实现。就像我们初始化一个对象的时候

OC :    [[Person alloc] init]        runtime :    objc_msgSend(objc_msgSend("Person" , "alloc"), "init")还有我们调用方法的时候,是这个样子的    OC:        [object  method]    Runtime:        object_msgSend(obj,@selector(method));

既然Runtime是属于OC的底层,name他就可以进行一些比较底层的操作。Objective-C能做的事情他能做,runtime能做的事情object-C就不一定能做到了,比如我们可以在程序运行的时候添加一个类,遍历一个类的成员,或者为某一个类添加一个属性,修改属性值之类的操作。

下面我们就举个例子用Runtime遍历模型属性,对属性进行归档结档操作。

第一步我们需要倒入相关的头文件,运行时相关的头文件一般都存放在头文件的/objc,比较常用的<objc/runtime.h>,<objc/message>

1. 可以先做一个测试,我在控制器的viewDidLoad里面写了一段代码,

        - (void)viewDidLoad {            [super viewDidLoad];                        unsigned int count = 0;            Ivar *ivars = class_copyIvarList([SQKPerson class], &count);                        for (int i = 0; i<count; i++) {                // 取出i位置对应的成员变量                Ivar ivar = ivars[i];                                // 查看成员变量                const char *name = ivar_getName(ivar);                NSLog(@"%s", name);            }

打印的结果是

2015-10-28 22:47:41.186 runtime[2312:108141] _age2015-10-28 22:47:41.186 runtime[2312:108141] _height2015-10-28 22:47:41.186 runtime[2312:108141] _name

3. 创建一个Person的类,声明了三个属性,age,height,name。

////  SQKPerson.m//  runtime////  Created by SQK on 15/10/28.//  Copyright © 2015年 SQK. All rights reserved.//#import "SQKPerson.h"#import <objc/runtime.h>/** *  进行归档接档,需要遵守NSCoding协议 */@interface SQKPerson ()<NSCoding>//在这里声明了属性@property (nonatomic, assign) int age;@property (nonatomic, assign) int height;@property (nonatomic, copy) NSString *name;@end@implementation SQKPerson- (void)encodeWithCoder:(NSCoder *)encode{    unsigned int count = 0;       Ivar *ivars = class_copyIvarList([SQKPerson class], &count);          for (int i = 0; i<count; i++) {         //获取Ivars成员变量        Ivar ivar = ivars[i];        //需要将name转成URTF8类型的        const char *name = ivar_getName(ivar);        NSString *key = [NSString stringWithUTF8String:name];        //归档        id value = [self valueForKey:key];        [encode encodeObject:value forKey:key];    }    //需要管理内存    free(ivars);}-(instancetype)initWithCoder:(NSCoder *)decoder{        if (self= [super init]) {        unsigned int  count = 0;        Ivar *ivars = class_copyIvarList([SQKPerson class], &count);        for (int i = 0; i<count; i++) {        //取出对应的成员变量            Ivar ivar = ivars[i];            const char *name = ivar_getName(ivar);            //结档            NSString *key = [NSString stringWithUTF8String:name];            //通过key取到成员变量(kvc)            id value = [decoder decodeObjectForKey:key];            //设置value到成员变量身上            [self setValue:value forKey:key];             }        free(ivars);    }    return self;}@end

如果我们模型中的属性很多的话,那么用这种方法进行操作是很方便的。

 

总之,runtime是很强大的一套语言库。在苹果的官方文档中也给出了详细的文档,对各种进行详细的解释

class_getName

class_addIvar

class_copyIvarList

class_getProperty

class_getPropertyList

....................

总而言之,Runtime是很好的一套东西,希望我们都能对他有所了解。我写这东西也是一边学一边写,难免避免有错误的见解。希望能和大家共同进步!

 

  相关解决方案