本地存储对象的方法
本节我们讲学习如何将创建的对象存储到本地文件中。存储对象,Foundation框架中提供了一个专门实现这个功能的类:NSKeyedArchiver和NSKeyedUnarchiver。
通过这两个类,我们就能够轻松地实现对对象进行存储和读取的功能,OC中对于对象的本地存储和读取有另外的称呼:
将对象存储到本地文件中被称作:归档。
从本地文件中读取数据的操作被称为:解档或者恢复。
通过归档和解档,可以实现将OC中的几种数据类型(必须转换成对象类型才能存储)或者是多个自定义对象保存到本地文件中,反之也可以。
下面通过例子来介绍一下,要想实现功能所要注意的细节:
创建一个工程,例如功能名为:Demo4;
创建完成之后,新建一个类,例如:Person类。
在Person类中添加几个属性或方法(随意,可以仿照例子)
做完上述准备工作后,我们需要让Person类中服从NSCoding协议:Foundation框架规定,对于每一个要实现将自定义对象存储到本地文件的类,都要服从NSCoding协议。
既然服从了NSCoding协议,就要实现协议中的用@required修饰的方法(简单的理解,就是如果要将一个对象进行归档或者解档,那么这个对象中的属性也必须要进行归档或者解档),所以这个协议中需要进行实现的只有两个方法;
-(void)encodeWithCoder:(NSCoder *)aCoder :从方法的命名就可以看出,这是归档的方法。
-(instancetype)initWithCoder:(NSCoder *)aDecoder :这是解档用到的方法。
下面来看一下具体的代码;
Person.h中的代码:
通过代码中解释,对于NSCoding协议应该有了一个基本的认识。通过上面的工作,Person类的代码已经编写完成了,下面我们通过一个例子来看一下怎么通过归档的方式将Person类的对象保存到本地文件中:
在main.m文件中编写以下代码:
解档一个对象
通过运行上边的代码,完成了将person1对象存储到a.txt文件中,下面来读取一下,尝试从a.txt文件中得到person1对象:
在main.m文件中编写以下代码:
归档多个对象
通过以上内容的学习,掌握了关于如何存储一个对象,那么如何储存多个对象呢,我们来继续学习一下:
在main.m文件中编写以下代码:
既然要练习存储多个对象,首先要建立至少两个对象person1和person2。
然后要确定存储对象的文件的路径path。
NSMutableData * data=[NSMutableData data]; NSMutableData是NSData类型的可变类型,通过看这个类提供的方法,我们很容易看到data类方法,它返回的是本类的对象(实际上是一个单例方法)。
NSKeyedArchiver * archiver=[[NSKeyedArchiver alloc] initForWritingWithMutableData:data];这行代码的作用是将归档对象和data可变类型相连接,这样的好处就是在后边归档的时候,数据都会保存在data对象中(这也是为什么使用二进制类型的可变类型的原因,归档一个,就添加一部分数据)。
[archiver encodeObject:person1 forKey:@"person1"];
[archiver encodeObject:person2 forKey:@"person2"];
上边两行分别对person1和person2两个对象进行归档。
[archiver finishEncoding];这行代码是结束归档的标志,当你归档完对象之后,一定要调用一下这个方法,否则会出错。
最后将归档完成获得的data存入文件中。
解档多个对象
通过上边的代码,我们可以将多个Person类的实例对象保存到本地文件中,那么我们再怎么读取呢?
在main.m文件中编写以下代码:
the person2's name is :LiSi,sex is :1,age is :20
解档代码分析
如果归档对象过多时,可以考虑将这些自定义对象保存到数组中,然后通过保存数组的方式存储过多的对象;当需要提取出这些数据时,可以将采用遍历数组的方式将自定义对象提取出来。
通过本节内容的学习之后,我们就可以对数据(包括基本数据和对象数据)进行永久的保存,同时,也能够实现对文件中的数据进行读取。
通过这两个类,我们就能够轻松地实现对对象进行存储和读取的功能,OC中对于对象的本地存储和读取有另外的称呼:
将对象存储到本地文件中被称作:归档。
从本地文件中读取数据的操作被称为:解档或者恢复。
通过归档和解档,可以实现将OC中的几种数据类型(必须转换成对象类型才能存储)或者是多个自定义对象保存到本地文件中,反之也可以。
下面通过例子来介绍一下,要想实现功能所要注意的细节:
创建一个工程,例如功能名为:Demo4;
创建完成之后,新建一个类,例如:Person类。
在Person类中添加几个属性或方法(随意,可以仿照例子)
做完上述准备工作后,我们需要让Person类中服从NSCoding协议:Foundation框架规定,对于每一个要实现将自定义对象存储到本地文件的类,都要服从NSCoding协议。
既然服从了NSCoding协议,就要实现协议中的用@required修饰的方法(简单的理解,就是如果要将一个对象进行归档或者解档,那么这个对象中的属性也必须要进行归档或者解档),所以这个协议中需要进行实现的只有两个方法;
-(void)encodeWithCoder:(NSCoder *)aCoder :从方法的命名就可以看出,这是归档的方法。
-(instancetype)initWithCoder:(NSCoder *)aDecoder :这是解档用到的方法。
下面来看一下具体的代码;
Person.h中的代码:
#import <Foundation/Foundation.h> @interface Person : NSObject<NSCoding> @property (nonatomic,copy)NSString * name; @property (nonatomic,assign)int age; @property (nonatomic,assign)BOOL sex; @endPerson.m中的代码:
#import "Person.h" @implementation Person -(void)encodeWithCoder:(NSCoder *)aCoder{ //在这个方法中要对类中声明的每个属性都要进行归档。 [aCoder encodeObject:self.name forKey:@"name"]; [aCoder encodeBool:self.sex forKey:@"sex"]; [aCoder encodeInt:self.age forKey:@"age"]; } -(instancetype)initWithCoder:(NSCoder *)aDecoder{ self.name=[aDecoder decodeObjectForKey:@"name"]; self.sex=[aDecoder decodeBoolForKey:@"sex"]; self.age=[aDecoder decodeIntForKey:@"age"]; //通过查找键找出对应的属性值,而这个键值就是在归档时候设置的值。 return self; } @end归档一个对象
通过代码中解释,对于NSCoding协议应该有了一个基本的认识。通过上面的工作,Person类的代码已经编写完成了,下面我们通过一个例子来看一下怎么通过归档的方式将Person类的对象保存到本地文件中:
在main.m文件中编写以下代码:
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { Person * person1=[[Person alloc] init]; person1.name=@"ZhangSan"; person1.sex=1; person1.age=10; NSString * path=@"/Users/xieyang/Desktop/a.txt"; [NSKeyedArchiver archiveRootObject:person1 toFile:path];//这行代码将person1对象归档到path这个路径下的文件中 return 0; }(提示:在mac下,如果你想知道某个文件的绝对路径,有一个简便方法:打开命令行,将文件直接拖到命令行下,你就可以直接得到这个文件的绝对路径)
解档一个对象
通过运行上边的代码,完成了将person1对象存储到a.txt文件中,下面来读取一下,尝试从a.txt文件中得到person1对象:
在main.m文件中编写以下代码:
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { NSString * path=@"/Users/xieyang/Desktop/a.txt"; Person * person=[NSKeyedUnarchiver unarchiveObjectWithFile:path];//在解档的时候,我们首先要找到文件,然后通过这个方法直接提取文件中的的对象 NSLog(@"the person's name is :%@,sex is :%d,age is :%d",person.name,person.sex,person.age); return 0; }输出结果:the person's name is :ZhangSan,sex is :1,age is :10
归档多个对象
通过以上内容的学习,掌握了关于如何存储一个对象,那么如何储存多个对象呢,我们来继续学习一下:
在main.m文件中编写以下代码:
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { Person * person1=[[Person alloc] init]; person1.name=@"ZhangSan"; person1.sex=1; person1.age=10; Person * person2=[[Person alloc] init]; person2.name=@"LiSi"; person2.sex=1; person2.age=20; //存储文件的路径 NSString * path=@"/Users/xieyang/Desktop/a.txt"; NSMutableData * data=[NSMutableData data]; NSKeyedArchiver * archiver=[[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; [archiver encodeObject:person1 forKey:@"person1"]; [archiver encodeObject:person2 forKey:@"person2"]; [archiver finishEncoding]; [data writeToFile:path atomically:YES]; return 0; }代码分析
既然要练习存储多个对象,首先要建立至少两个对象person1和person2。
然后要确定存储对象的文件的路径path。
NSMutableData * data=[NSMutableData data]; NSMutableData是NSData类型的可变类型,通过看这个类提供的方法,我们很容易看到data类方法,它返回的是本类的对象(实际上是一个单例方法)。
NSKeyedArchiver * archiver=[[NSKeyedArchiver alloc] initForWritingWithMutableData:data];这行代码的作用是将归档对象和data可变类型相连接,这样的好处就是在后边归档的时候,数据都会保存在data对象中(这也是为什么使用二进制类型的可变类型的原因,归档一个,就添加一部分数据)。
[archiver encodeObject:person1 forKey:@"person1"];
[archiver encodeObject:person2 forKey:@"person2"];
上边两行分别对person1和person2两个对象进行归档。
[archiver finishEncoding];这行代码是结束归档的标志,当你归档完对象之后,一定要调用一下这个方法,否则会出错。
最后将归档完成获得的data存入文件中。
解档多个对象
通过上边的代码,我们可以将多个Person类的实例对象保存到本地文件中,那么我们再怎么读取呢?
在main.m文件中编写以下代码:
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { NSString * path=@"/Users/xieyang/Desktop/a.txt"; NSData * theData=[NSData dataWithContentsOfFile:path]; NSKeyedUnarchiver * unarchiver=[[NSKeyedUnarchiver alloc]initForReadingWithData:theData]; Person * thePerson1=[unarchiver decodeObjectForKey:@"person1"]; NSLog(@"the person1's name is :%@,sex is :%d,age is :%d",thePerson1.name,thePerson1.sex,thePerson1.age); Person * thePerson2=[unarchiver decodeObjectForKey:@"person2"]; NSLog(@"the person2's name is :%@,sex is :%d,age is :%d",thePerson2.name,thePerson2.sex,thePerson2.age); return 0; }输出结果:the person1's name is :ZhangSan,sex is :1,age is :10
the person2's name is :LiSi,sex is :1,age is :20
解档代码分析
- 首先我们要知道解档文件的路径path,而且确定这个文件中的数据是通过上面的方式归档的;
- 由于采用上边的方式归档的是一个NSMutableData类型的数据,所以我们可以用NSData类型的对象去接。
- 获得二进制数据之后,由于我们无法直接对二进制数据进行操作,所以还得先将数据解档才行。
- 解档之后我们就可以通过这个decodeObjectForKey方法根据键来查找对应的对象
如果归档对象过多时,可以考虑将这些自定义对象保存到数组中,然后通过保存数组的方式存储过多的对象;当需要提取出这些数据时,可以将采用遍历数组的方式将自定义对象提取出来。
通过本节内容的学习之后,我们就可以对数据(包括基本数据和对象数据)进行永久的保存,同时,也能够实现对文件中的数据进行读取。