runTime

作者: 严木木 | 来源:发表于2016-03-21 09:56 被阅读349次

    iOS runtime讲解,并且用runtime动态归档与解档 (2015-09-30 22:42:02)转载▼

    标签: c语言 底层 属性 变量 分类: 个人总结的一些实用技术

    //

    //  AppDelegate.m

    //  Runtime自动归档

    //

    //  Created by CONGAING on 15/7/13.

    //  Copyright (c) Congwang. All rights reserved.

    //

    #import "AppDelegate.h"

    #import "Student.h"

    @interface AppDelegate ()

    @end

    @implementation AppDelegate

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Override point for customization after application launch.

    self.window.backgroundColor = [UIColor whiteColor];

    [self.window makeKeyAndVisible];

    //  runtime:运行时机制

    //  1.是什么?

    //  1.1runtime是一套比较底层的纯C语言的API,runtime就是一个库,一个C语言库,包含了许多底层的C语言API

    //  1.2平时我们编写的OC代码,在程序运行过程中,其实最终都是转成了runtime的C语言代码,runtime算是OC的幕后工作者,是整个OC的底层

    //  1.3举个例子

    //  oc中的代码:[Student alloc] init]经过runtime后,其实最终在底层生成C语言代码:

    //  objc_msgSend(objc_msgSend("Student","alloc"), "init")

    //  objc_msgSend其实就是想某个对象发送什么消息,这个函数第一个参数是类型或对象名,第二个参数是消息的名字,这些代码比较底层

    //  2.用过吗?怎么用?

    //  2.1 runtime是属于OC的底层,可以进行一些非常底层的操作(用OC无法实现的,或者说不好实现)eg

    //  *在程序运行过程中,动态创建一个类,(比如KVO和KVC的底层实现)

    //  *在程序运行过程中,动态为某个类添加属性/方法,修改属性值,修改方法

    //  *遍历一个类中所有的属性和实例变量和所有方法

    //  3.

    //  3.1相关的头文件

    //  #import

    //  #import //消息发送机制,可以直接用底层函数,进行消息发送

    //  3.2相关应用

    //  *NSCoding(归档和解挡)

    //  *字典转模型(利用runtime遍历模型对象的所有属性,根据属性名从字典中取出对应的值,设置到模型的属性上)

    //  *kvo(利用runtime动态产生一个类)

    //  3.3相关函数

    //  msg_send:给对象发送消息,来自

    //  class_copyMethodList,遍历某个类中所有的方法,来自

    //  class_copyIvarList,遍历某个类中所有的实例变量的方法,来自

    //  运行时必备常识:

    //  1.Ivar:成员变量的意思

    //  2.Method:成员方法的意思

    //  3.property:属性

    //  下面我们开始实现动态归档

    //  打开student.m,引入

    Student *student = [[Student alloc] init];

    student.name1 = @"sunlin";

    student.age = 18;

    student.name2 = @"sunlin";

    student.name3 = @"sunlin";

    student.name4 = @"sunlin";

    student.name5 = @"sunlin";

    student.name6 = @"sunlin";

    student.name7 = @"sunlin";

    //  归档文件的路径

    NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"person.archiver"];

    //  判断该文件是否存在

    if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {

    //  不存在的时候,归档存储一个Student的对象

    NSMutableData *data = [NSMutableData data];

    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

    [archiver encodeObject:student forKey:@"student"];

    [archiver finishEncoding];

    BOOL success = [data writeToFile:filePath atomically:YES];

    if (success) {

    NSLog(@"归档成功!");

    }

    } else{

    //  存在的时候,不再进行归档,而是解挡!

    NSData *data = [NSData dataWithContentsOfFile:filePath];

    NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];

    Student *studentFromSaving = [unArchiver decodeObjectForKey:@"student"];

    NSLog(@"%@, %lu", studentFromSaving.name7, studentFromSaving.age);

    }

    return YES;

    }

    @end

    //

    //  Student.h

    //  Runtime自动归档

    //

    //  Created by王聪 on 14/7/13.

    //  Copyright (c) 2015年congWang. All rights reserved.

    //

    #import

    #import

    @interface Student : NSObject

    @property (nonatomic, assign) NSInteger age;

    @property (nonatomic, copy) NSString *name1;

    @property (nonatomic, copy) NSString *name2;

    @property (nonatomic, copy) NSString *name3;

    @property (nonatomic, copy) NSString *name4;

    @property (nonatomic, copy) NSString *name5;

    @property (nonatomic, copy) NSString *name6;

    @property (nonatomic, copy) NSString *name7;

    @end

    //

    //  Student.m

    //  Runtime自动归档

    //

    //  Created by 王聪 on 15/7/13.

    //  Copyright (c) 2015年 王聪. All rights reserved.

    //

    #import "Student.h"

    @implementation Student

    - (void)encodeWithCoder:(NSCoder *)encoder

    {

    unsigned int count = 0;

    //  利用runtime获取实例变量的列表

    Ivar *ivars = class_copyIvarList([self class], &count);

    for (int i = 0; i < count; i ++) {

    //  取出i位置对应的实例变量

    Ivar ivar = ivars[i];

    //  查看实例变量的名字

    const char *name = ivar_getName(ivar);

    //  C语言字符串转化为NSString

    NSString *nameStr = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];

    //  利用KVC取出属性对应的值

    id value = [self valueForKey:nameStr];

    //  归档

    [encoder encodeObject:value forKey:nameStr];

    }

    //  记住C语言中copy出来的要进行释放

    free(ivars);

    }

    - (id)initWithCoder:(NSCoder *)decoder

    {

    if (self = [super init]) {

    unsigned int count = 0;

    Ivar *ivars = class_copyIvarList([self class], &count);

    for (int i = 0; i < count; i ++) {

    Ivar ivar = ivars[i];

    const char *name = ivar_getName(ivar);

    //

    NSString *key = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];

    id value = [decoder decodeObjectForKey:key];

    //  设置到成员变量身上

    [self setValue:value forKey:key];

    }

    free(ivars);

    }

    return self;

    }

    @end

    相关文章

      网友评论

        本文标题:runTime

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