在平时的iOS开发中,我们经常用到的数据持久化存储方式大概主要有:NSUserDefaults(plist),文件,数据库,归档。。前三种比较经常用到,第四种归档我个人感觉用的还是比较少的,恰恰因为用的比较少,但是还是有地方要用到,所以今天再把归档解档复习一遍吧。

一、什么是归档:

  对象归档是将对象以文件的形式保存到磁盘中(也称为序列化,持久化) ;使用的时候读取该文件的保存路径读取文件的内容(也称为解档,反序列化)。

二、归档 与 plist存储的区别:

  • 对象归档的文件是保密的,在磁盘上无法查看文件中的内容,而plist属性列表是明文的可以查看。
  • 其次就是保存的数据类型不同
    • 只要是对象类型,归档都可以保存。
    • 而plist只能保存这几种类型:NSString  NSNumber  NSDate NSData NSArray NSDictionary  。不能保存其他的类型

三、归档的使用

  刚刚说到,只要是对象类型,都可以用归档的方式进行保存。

  但是,只有实现了<NSCoding>协议的类型才可以进行归档,由于Foudation框架中的对象类型已经实现了NSCoding协议,所以可以直接归档解档,而我们自定义的类型,则需要我们手动去实现NSCoding协议。必须实现一下两个方法:

//归档的时候调用的方法
- (void)encodeWithCoder:(NSCoder *)aCoder;
//解归档的时候要调用的函数
- (id)initWithCoder:(NSCoder *)aDecoder;

  1.对系统类的归档:

    第一种方式:单个对象的归档和解档

//单个对象归档:
NSArray *array1 = @[@"zhangsan",@"wangwu",@"lisi"];
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
BOOL success = [NSKeyedArchiver archiveRootObject:array1 toFile:filePath];
if (success) {
NSLog(@"保存成功!");
}
//单个对象解档
id array2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@",array2);

    第二种方式:多个对象的归档和解档

    //多个对象归档:
NSArray *array1 = @[@"zhangsan",@"wangwu",@"lisi"];
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//编码
[archiver encodeObject:array1 forKey:@"array"];
[archiver encodeInt: forKey:@"scope"];
[archiver encodeObject:@"jack" forKey:@"name"];
//完成编码,讲上面的归档数据填充到data中,此时data已经存储了归档对象的数据
[archiver finishEncoding];
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
BOOL success = [data writeToFile:filePath atomically:YES];
if (success) {
NSLog(@"归档成功");
} //多个对象解档
NSData *data2 = [[NSData alloc] initWithContentsOfFile:filePath];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data2];
NSArray *array = [unarchiver decodeObjectForKey:@"array"];
NSLog(@"%@",array);
int value = [unarchiver decodeIntForKey:@"scope"];
NSLog(@"%d",value);
  [unarchiver finishDecoding];

  2.自定义类型的归档解档

  上面已经说过了,对系统类型可以直接进行归档和解档,但是对于自定义类型,必须实现NSCoding协议

#import <Foundation/Foundation.h>
#import "Car.h" int main(int argc, const char * argv[])
{
/*
有辆汽车 有一个引擎 和 四个轮胎 然后需要对这个汽车进行归档 本地保存数据
这时 还必须要对汽车的引擎和轮胎也要归档 只要有成员变量是对象地址 都要继续归档 那么这时归档的类 都要遵守协议NSCoding 实现里面的方法 实际上 归档就是一个深拷贝
*/ @autoreleasepool { #if 0
Car *BMW = [[Car alloc] init];
BMW.speed = ;
[BMW run]; //程序结束之前把汽车对象的信息进行保存到本地
//归档 NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"car.src"]; BOOL ret = [NSKeyedArchiver archiveRootObject:BMW toFile:filePath];
if (ret) {
NSLog(@"汽车对象归档成功");
}else {
NSLog(@"汽车归档失败");
}
[BMW release]; #else
//解归档-->从文件中获取数据创建一个Car对象 NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"car.src"]; Car *car = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; NSLog(@"car.speed:%ld",car.speed);
NSLog(@"engine.name:%@",car.engine.name);
[car run]; #endif }
return ;
}

  汽车类:

#import <Foundation/Foundation.h>
#import "Engine.h"
#import "Tyre.h" //遵守归档协议
@interface Car : NSObject<NSCoding>
{
Engine *_engine;
NSMutableArray *_tyresArr;
NSInteger _speed;
}
@property (nonatomic) NSInteger speed;
@property (nonatomic,retain) Engine *engine;
- (Car *)init;
- (void)run;
@end
#import "Car.h"

@implementation Car
- (void)dealloc {
NSLog(@"汽车销毁");
[_engine release];
[_tyresArr release];
[super dealloc];
} //对Car归档的时候会调用的方法
- (void)encodeWithCoder:(NSCoder *)aCoder {
//就是对成员变量的数据进行归档
//如果成员变量是基本类型 那么直接归档
//如果成员变量变量是对象地址 那么对象的类也要遵守协议实现方法 //在类中 如果有setter和getter方法那么尽量使用setter和getter方法
[aCoder encodeInteger:self.speed forKey:@"speed"];
//对一个对象地址指向的对象进行归档 那么指向对象也要实现归档协议的方法 Engine 要遵守 数组要遵守 数组的元素也要遵守
[aCoder encodeObject:self.engine forKey:@"engine"];
[aCoder encodeObject:_tyresArr forKey:@"array"];
}
//对象解归档、读档的时候调用
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {//如果父类有initWithCoder那么调用父类的initWithCoder: //这里不要直接写 成员变量 否则就有可能崩溃
//要用setter方法 这样 内部会计数器+1 拥有绝对使用权
//读档
self.engine = [aDecoder decodeObjectForKey:@"engine"];
NSLog(@"%ld",self.engine.retainCount);
self.speed = [aDecoder decodeIntegerForKey:@"speed"];
//要注意拥有绝对使用权
_tyresArr = [[aDecoder decodeObjectForKey:@"array"] retain]; }
return self;
} - (Car *)init {
if (self = [super init]) {
_engine = [[Engine alloc] init];
_engine.name = @"德国";
_engine.power = ; _tyresArr = [[NSMutableArray alloc] init];
for (int i = ; i < ; i++) {
Tyre *tyre = [[Tyre alloc] init];
tyre.name = @"米其林";
tyre.type = ;
[_tyresArr addObject:tyre];
[tyre release];
}
}
return self;
}
- (void)run {
NSLog(@"汽车跑");
[self.engine start];
for (Tyre *tyre in _tyresArr) {
[tyre scroll];//滚动
}
} @end

轮胎类:

#import <Foundation/Foundation.h>

@interface Tyre : NSObject<NSCoding>
{
NSString *_name;
NSInteger _type;
}
@property (nonatomic,copy)NSString *name;
@property (nonatomic)NSInteger type;
- (void)scroll; @end
#import "Tyre.h"

@implementation Tyre
- (void)dealloc {
NSLog(@"轮胎销毁");
self.name = nil;
[super dealloc];
}
//归档调用
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.type forKey:@"type"];
}
//读档调用
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
//用setter方赋值 内部有计数器+1
self.name = [aDecoder decodeObjectForKey:@"name"];
self.type = [aDecoder decodeIntegerForKey: @"type"];
}
return self;
} - (void)scroll {
NSLog(@"%@ 轮胎在滚动",self.name);
}
@end

引擎类:

#import <Foundation/Foundation.h>

@interface Engine : NSObject <NSCoding>
{
NSString *_name;
NSInteger _power;
}
@property (nonatomic,copy)NSString *name;
@property (nonatomic) NSInteger power;
- (void)start;
@end
#import "Engine.h"

@implementation Engine
- (void)dealloc {
NSLog(@"引擎销毁");
self.name = nil;
[super dealloc];
}
//归档调用
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.power forKey:@"power"];
}
//读档调用
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.power = [aDecoder decodeIntegerForKey: @"power"];
}
return self;
} - (void)start {
NSLog(@"引擎启动");
}
@end
 
 

iOS数据持久化存储:归档的更多相关文章

  1. iOS开发笔记-swift实现iOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (plist.NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data.第三方类库等 归档(又名 ...

  2. IOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (自定义的Property List .NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data ...

  3. 转载 -- iOS数据持久化存储

    作者:@翁呀伟呀 授权本站转载 概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方 ...

  4. IOS数据持久化之归档NSKeyedArchiver, NSUserDefaults,writeToFile

    //2.文件读写 //支持:NSString, NSArray , NSDictionay, NSData //注:集合(NSArray, NSDictionay)中得元素也必须是这四种类型, 才能够 ...

  5. iOS数据持久化存储之属性列表

    属性列表(plist) iOS提供了一种plist格式的文件(属性列表)用于存储轻量级的数据,属性列表是一种XML格式的文件,拓展名为plist.如果对象是NSString.NSDictionary. ...

  6. iOS数据持久化存储

    本文中的代码托管在github上:https://github.com/WindyShade/DataSaveMethods 相对复杂的App仅靠内存的数据肯定无法满足,数据写磁盘作持久化存储是几乎每 ...

  7. iOS数据持久化存储之归档NSKeyedArchiver

    归档是一种很常用的文件储存方法,几乎任何类型的对象都能够被归档储存(实际上是一种文件保存的形式),收集了网上的一些资料并结合自己的一些经验,总结如下. 一.使用archiveRootObject进行简 ...

  8. IOS数据持久化存储之SQLite3第三方库FMDB的使用

    SQLite是一种小型的轻量级的关系型数据库,在移动设备上使用是非常好的选择,无论是Android还是IOS,都内置了SQLite数据库,现在的版本都是SQLite3.在IOS中使用SQLite如果使 ...

  9. iOS开发——数据持久化Swift篇&使用Core Data进行数据持久化存储

    使用Core Data进行数据持久化存储   一,Core Data介绍 1,Core Data是iOS5之后才出现的一个数据持久化存储框架,它提供了对象-关系映射(ORM)的功能,即能够将对象转化成 ...

随机推荐

  1. Telnet连接Win7系统被拒绝的原因及解决方法

    有时要与计算机进行远程连接,会用到telnet.win7中telnet默认是没有开启的,所以这时连接会连接失败,其失败提示如下: 正在连接192.168.100.103...无法打开到主机的连接. 在 ...

  2. iOS单例 宏定义

    #define singleton_interface(className) \ + (className *)shared##className; // @implementation #defin ...

  3. myeclipse 8.5安装freemarker插件方法

    1. 下载freemarker最新版本,目前本人下载时最新版本是:freemarker-ide-0.9.14.zip, ide版本的freemarker.jar版本太低,可以替换成高级版本,并修改me ...

  4. installshield 注册dll

    function OnFirstUIAfter() STRING szTitle, szMsg1, szMsg2, szOpt1, szOpt2; NUMBER bOpt1, bOpt2; begin ...

  5. android ListView进阶

    ListView 1.在android 开发中很多时候都要用到ListView的这个控件的,但用这个控件的时候会遇到一些问题,如在ListView中有Button按钮,就需要将按钮的监听事件给分离出来 ...

  6. 批处理脚本命令行方式关闭Windows服务

    对于一些不常用的Windows Services,可以通过设置其启动类型为"禁用"而将其关闭.这种关闭方式是长期性的,电脑重启之后仍然起作用. 有时候希望在批处理脚本里通过命令行方 ...

  7. 导入导出Excel

    最近需要频繁的使用导入导出,各么,又不想使用ms的PIA,在4.0以下,存在版本兼容的问题. 于是网上查找了很久,找到两款开源的excel组件. 1.CSharpJExcel,这是JExcel的.ne ...

  8. (C++)STL排序函数sort和qsort的用法与区别

    主要内容: 1.qsort的用法 2.sort的用法 3.qsort和sort的区别 qsort的用法: 原 型: void qsort(void *base, int nelem, int widt ...

  9. mac下xampp简单虚拟主机配置

    多域名,虚拟主机的配置 开启虚拟主机配置选项: 打开httpd.conf文件,找到httpd-vhosts.conf那一行,解除该行注释: 打开httpd-vhosts.conf文件 修改如下 < ...

  10. Hadoop on Mac with IntelliJ IDEA - 6 解决KeyValueTextInputFormat读取时只有key值问题

    本文讲述使用KeyValueTextInputFormat在Hadoop 0.x正常工作.Hadoop 1.2.1失效的解决过程. 环境:Mac OS X 10.9.5, IntelliJ IDEA ...