【已解决】iPhone/iOS中保存自定义对象(Custom Object/Custom Class)的数组(NSMutableArray/NSArray)到NSUserDefaults
2016-01-04 23:48
721 查看
【已解决】iPhone/iOS中保存自定义对象(Custom Object/Custom Class)的数组(NSMutableArray/NSArray)到NSUserDefaults
2012年 11 月 26 日 上午 12:57crifan已有17063人围观7个评论
【问题】
在折腾:
给Your
Second iOS App:BirdWatching添加支持程序退出后,用户数据仍然保留
的过程中,遇到一个问题,需要将一个自定义对象的数组,保存到NSUserDefaults。
【解决过程】
1.经过学习很多资料后,然后加上一番折腾,先去实现了单个自定义对象的编解码和存储/恢复:
贴出部分相关的代码:
BirdSighting.h:
?
?
?
2.后来也参考了很多帖子:
How
to store custom objects in NSUserDefaults
save
and restore an array of custom objects
How
to archive an NSArray of custom objects to file in Objective-C
3.但是我这里又遇到一个问题,那就是,我此处需要保存的是自定义对象的数组,即用一个数组指针指向的多个自定义对象,所以,就没法直接使用上述方法保存这一系列自定义对象了,所以还要想其他办法才行。
但是后来却发现,其实上述原先的代码,本身已经可以工作了。
即,解码的时候,可以看到能从NSUserDefaults获得一堆的数据了:
对应的,在恢复自定义对象数组masterBirdSightingList之前,其是null:
然后调用unarchiveObjectWithData时,也可以执行对应的自定义对象的initWithCoder函数了:
解码后,对应的masterBirdSightingList就包含了还原出来的2个对象了:
而编码过程也是所期望的:
先是NSData是空的:
然后调用archivedDataWithRootObject去编码,可以调用到自定义对象的encodeWithCoder函数:
然后经过4个对象的编码后,就包含了编码后的数据了:
接着就是正常的保存到NSUserDefaults中去了.
如此,关闭程序之前的显示的数据是:
恢复后的显示的效果为:
很明显,两者完全一样,即整套逻辑是正常工作的,可以完美的实现自定义对象的数组的保存和恢复.
下面对整个逻辑和示例代码,进行详细的总结。
【总结】
【自定义对象的数组NSMutableArray,保存到/恢复自
NSUserDefaults 的逻辑】
想要实现自定义类型的对象的数组,保存到NSUserDefaults中去,核心的逻辑是:
1.想要把数据保存到NSUserDefaults中的话,那首先要知道NSUserDefaults所支持的数据类型。
根据官网
NSUserDefaults
Class Reference
的解释,默认支持类型是:
NSData
NSString
NSNumber
NSDate
NSArray
NSDictionary
所以,如果你本身要保存的数据是属于上述中已有的,常见的,数据类型,比如NSString,NSDate之类的话,那么很简单,直接保存即可。
2.而此处所谓的自定义对象(Custom Object)/类(Class)的话,常见的做法是,把自定义对象转换为NSData,然后利用NSUserDefaults去保存NSData。
把自定义对象转换为NSData,用的方法就是Archive,Archive可翻译为归档,压缩。
相关的方法是:
NSKeyedArchiver
Class Reference 的
+ archivedDataWithRootObject:
NSKeyedUnarchiver
Class Reference 的
+ unarchiveObjectWithData:
对应的,自定义对象本身,需要遵循NSCoding,其有两个函数:
– initWithCoder::解码
– encodeWithCoder:: 编码
3. 之后:
当你的使用NSKeyedArchiver去把自定义对象编码为NSData时,就会调用到该对象的encodeWithCoder,编码后得到了NSData后,再保存到NSUserDefaults里面;
当你从NSUserDefaults读取出你之前所保存的NSData之后,再调用NSKeyedUnarchiver去解码此NSData,然后内部会自动调用到该自定义对象的initWithCoder方法,将NSData解码为对应的自己的对象
如此,就可以实现将自定义对象保存到NSUserDefaults和从NSUserDefaults恢复之前保存的自定义对象了。
4.上述方法,看似是只针对单个自定义对象的,但是本质上,对于自定义对象的数组,也是适用的。
因为,对于一般的NSMutableArray来说,其本身也是实现了NSCoding,所以,当你去使用NSKeyedArchiver将一个自定义对象的NSMutableArray数组编码为NSData时,其内部会先调用NSMutableArray的encodeWithCoder,然后发现是个自定义对象的数组,然后就会分别针对每个自定义对象调用该自定义对象的encodeWithCoder,这样,最终实现了将整个自定义对象数组,转换为NSData;
相应的解码过程也是一样的,当从NSData解码为对应的自定义对象的NSMutableArray数组时,也是先调用NSMutableArray的initWithCoder,然后分别调用每个自定义对象的initWithCoder,最终解码为对应的自定义对象的NSMutableArray数组。
【自定义对象的数组NSMutableArray,保存到/恢复自
NSUserDefaults 的 参考代码】
1. 自定义对象BirdSighting
(1)对应的头文件中:
A. 实现了遵循NSCoding(Conform to NSCoding)
B. 包含了几个自己的不同类型的属性
?
A。实现了对应的NSCoding的encodeWithCoder,将对应的不同的属性变量编码为对应数据
B。实现了对应的NSCoding的initWithCoder,从对应的 key中解码出数据还原到对应的属性变量中
?
先说背景条件:
BirdSightingDataController是个Controller
在对应的头文件BirdSightingDataController.h中,定义了个属性变量,是 自定义对象BirdSighting的数组 NSMutableArray
?
以及对应的也可以从NSUserDefaults中还原出masterBirdSightingList。
(1)编码 masterBirdSightingList(自定义对象BirdSighting的数组NSMutableArray) 到 NSUserDefaults 中
?
?
如此,就可以实现,将 自定义对象的数组 保存到 NSUserDefaults 了。
特别提示:
如果你遇到数据偶尔没有保存成功的话,那和你要保存的变量,以及NSCoder对象是否是autoRelease的,没有半毛钱关系,而是和iOS中数据同步写回有关系。
解决办法参见:
【已解决】NSUserDefaults偶尔/有时候保存数据会失败/失效
相关文章推荐
- IOS开发系列--Objective-C之KVC、KVO
- Objective-c:isKindOfClass 与 isMemberOfClass
- [Objective-C] id类型和instancetype类型
- Objective-c:类簇
- IOS开发基础Object-C( 14)-- 字符串的使用方法
- 【Objective-C学习记录】第三十四天
- Debugging Objects
- objective-c中实现函数重载(黑魔法:__attribute__((overloadable)))
- Object-c __attribute__((overloadable))) 用法
- 预定义的类型System.Object未定义或未导入
- JSONObject使用方法
- Uinty ScriptableObject的用法
- 如何使用GameObject类发送消息
- iOS UIView动画详解(Objective-C)
- DELPHI调用JAVA WEBSERVICE方法 出现 null object 异常的原因
- Objective-C学习篇第十二弹:键值观察KVO详解
- 使用Objective-C获取每日必应壁纸设置为桌面
- Objective-C类方法中使用self注意事项
- Objective-C中@property的所有属性详解
- objective-c dictionary(字典)