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