一、runtime实现通用copy

如果自定义类的子类,模型套模型你真的会copy吗,小心有坑。

copy需要自定义类继承NSCopying协议

#import <objc/runtime.h>

- (id)copyWithZone:(NSZone *)zone {

    id obj = [[[self class] allocWithZone:zone] init];
Class class = [self class];
while (class != [NSObject class]) {
unsigned int count;
Ivar *ivar = class_copyIvarList(class, &count);
for (int i = ; i < count; i++) {
Ivar iv = ivar[i];
const char *name = ivar_getName(iv);
NSString *strName = [NSString stringWithUTF8String:name];
//利用KVC取值
id value = [[self valueForKey:strName] copy];//如果还套了模型也要copy呢
[obj setValue:value forKey:strName];
}
free(ivar); class = class_getSuperclass(class);//记住还要遍历父类的属性呢
}
return obj;
}

二、runtime实现通用归档解档

归档解档需要自定义类继承NSCoding协议

#import <objc/runtime.h>

#pragma mark - 归档、解档
- (void)encodeWithCoder:(NSCoder *)encoder { Class class = [self class];
while (class != [NSObject class]) {
unsigned int count;
Ivar *ivar = class_copyIvarList(class, &count);
for (int i = ; i < count; i++) {
Ivar iv = ivar[i];
const char *name = ivar_getName(iv);
NSString *strName = [NSString stringWithUTF8String:name];
//利用KVC取值
id value = [self valueForKey:strName];
[encoder encodeObject:value forKey:strName];
}
free(ivar); class = class_getSuperclass(class);//记住还要遍历父类的属性呢
}
} - (id)initWithCoder:(NSCoder *)decoder {
self = [super init];
if (self) { Class class = [self class];
while (class != [NSObject class]) {
unsigned int count = ;
//获取类中所有成员变量名
Ivar *ivar = class_copyIvarList(class, &count);
for (int i = ; i < count; i++) {
Ivar iva = ivar[i];
const char *name = ivar_getName(iva);
NSString *strName = [NSString stringWithUTF8String:name];
//进行解档取值
id value = [decoder decodeObjectForKey:strName];
//利用KVC对属性赋值
[self setValue:value forKey:strName];
}
free(ivar); class = class_getSuperclass(class);//记住还要遍历父类的属性呢
}
}
return self;
}

三、NSUserDefaults存储自定义对象

//1.自定义类继承NSCoding协议,并实现归档解档,前面介绍过了,不多说

//2.将自定义对象转NSData
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:student]; //3.存到NSUserDefaults
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"myStudent"];
[[NSUserDefaults standardUserDefaults] synchronize];//这句要写,很多人都忘了 //4.存数组,数组中包含自定义对象
[dataArray addObject:data];//这个data是第2步归档得到的data //5.NSUserDefaults只能存不可变数组,不要忘了转换成不可变
NSArray * array = [NSArray arrayWithArray:dataArray];
[[NSUserDefaults standardUserDefaults] setObject:array forKey:@"students"];

四、NSUserDefaults中读取归档的自定义对象

NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"myStudent"];
Student *student = [NSKeyedUnarchiver unarchiveObjectWithData:data];

iOS 自定义对象及子类及模型套模型的拷贝、归档存储的通用代码的更多相关文章

  1. iOS 自定义对象转NSDictionary

    我们在向后台Post数据的时候,常常需要把某个对象作为参数,比如在AF的框架中,我们进行Post时,其中的para参数就是需要NSdictionary的 Alamofire.request(.POST ...

  2. iOS开发——UI进阶篇(十一)应用沙盒,归档,解档,偏好设置,plist存储,NSData,自定义对象归档解档

    1.iOS应用数据存储的常用方式XML属性列表(plist)归档Preference(偏好设置)NSKeyedArchiver归档(NSCoding)SQLite3 Core Data 2.应用沙盒每 ...

  3. JavaScript---网络编程(5)-自定义对象Json、Dom模型概念讲解

    这节博客主要讲解Dom模型概念~和JSON的简单介绍 首先,还是先上out.js的代码: function println(param){ document.write(param+"< ...

  4. Keras处理已保存模型中的自定义层(或其他自定义对象)

    如果要加载的模型包含自定义层或其他自定义类或函数,则可以通过 custom_objects 参数将它们传递给加载机制: from keras.models import load_model # 假设 ...

  5. ios深拷贝,浅拷贝,拷贝自定义对象的简单介绍(转)

    copy语法的目的:改变副本的时候,不会影响到源对象: 深拷贝:内容拷贝,会产生新的对象.新对象计数器置为1,源对象计数器不变. 浅拷贝:指针拷贝,不会产生新的对象.源对象计数器+1. 拷贝有下面两个 ...

  6. ios存储 plist 偏好设置 自定义对象存储

    1,plist Plist注意:不能存储自定义对象 Plist:数组和字典,  如何判断一个对象能不能使用Plist,就看下有没有writeToFile 获取应用的文件夹(应用沙盒) NSString ...

  7. iOS 深拷贝、浅拷贝、自定义对象拷贝简介

    copy语法的目的:改变副本的时候,不会影响到源对象: 深拷贝:内容拷贝,会产生新的对象.新对象计数器置为1,源对象计数器不变. 浅拷贝:指针拷贝,不会产生新的对象.源对象计数器+1. 拷贝有下面两个 ...

  8. IOS 如何持久化自定义对象 2014-08-01 01:38

    如果持久话自定义对象 那么这个对象一定要遵循 NSCoding 协议 并实现编解码:然后再将编解码后的数据 NSKeyedArchiver 到NSData中   @interface NSKeyAnd ...

  9. 如何理解iOS的“对象等同性”

    在iOS开发过程中,我们经常需要用到等同性来判断两个对象是否相等,通常我们会使用==来判断,但是这样比较出来的结果可能不是我们期望的:所以,一般我们会使用NSObject协议声明的isEqual方法来 ...

随机推荐

  1. linux编程之共享内存

    linux 进程间通信(IPC)包括3种机制:消息队列.信号量.共享内存.消息队列和信号量均是内核空间的系统对象,经由它们 的数据需要在内核和用户空间进行额外的数据拷贝:而共享内存和访问它的所有应用程 ...

  2. 使用GDB命令行调试器调试C/C++程序【转】

    转自:https://linux.cn/article-4302-1.html 编译自:http://xmodulo.com/gdb-command-line-debugger.html作者: Adr ...

  3. Linux线程基础函数

    1. 线程标识: (1) 比较两个线程ID: #include <pthread.h> int pthread_equal(pthread_t tid1, pthread_t tid2); ...

  4. 己动手创建最精简的Linux

    己动手创建最精简的Linux http://blog.sina.com.cn/s/blog_71c87c170101e7ru.html 首次 LFS 搭建全过程 http://zmyxn.blog.5 ...

  5. Python简单的制作图片验证码

    -人人可以学Python--这里示范的验证码都是简单的,你也可以把字符扭曲 人人可以学Python.png Python第三方库无比强大,PIL 是python的一个d第三方图片处理模块,我们也可以使 ...

  6. Android端与Android端利用WIFI进行FTP通信

    一.客户端通信工具类: import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; im ...

  7. NOIP 2012 Day2

    tags: 扩展欧几里得 二分答案 查分 倍增 二分答案 贪心 NOIP categories: 信息学竞赛 总结 同余方程 借教室 疫情控制 同余方程 Solution 首先同余式可以转化为等式. ...

  8. 自动关闭IO流-jdk1.7版本

    public static void main(String[] args) throws IOException { try( FileInputStream fis = new FileInput ...

  9. spring使用aop需要的jar包,和常见异常

    3.0以后spring不再一起发布aop依赖包,需要自己导入: 必须包: 这几个jar包分别为 1.org.springframework.aop-3.1.1.RELEASE  这个是spring的 ...

  10. Fel表达式使用过程中需要注意的问题

    精度问题: 我们知道java中直接使用float和double参与的计算都可能会产生精度问题,比如0.1+0.3.1.0-0.9 等.所以一般财务系统,都会使用BigDecimal进行加减乘除. 在调 ...