@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);

@import url(/css/cuteeditor.css);

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);

@import url(/css/cuteeditor.css);

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);

@import url(/css/cuteeditor.css);

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);

@import url(/css/cuteeditor.css);

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);

@import url(/css/cuteeditor.css);

1. 基础知识

1.1 简介

数据持久存储是一种非易失性存储,在重启动计算机或设备后也不会丢失数据。持久化技术主要用于MVC模型中的model层。其中目前再IOS平台上主要使用如下的四种技术:

  • 属性列表
  • 对象归档
  • SQLite3
  • Core Data

其中需要注意的是,在IOS开发中除了上述4种最简单持久化技术外,还可以使用传统C语言I/O调用(比如fopen())读取和写入数据,也可以使用Cocoa的底层文件管理工具。

1.2 沙盒(SandBox)

       IOS中的沙盒机制(SandBox)是一种安全体系,它规定了应用程序只能在为该应用创建的文件夹内读取文件,不可以访问其他地方的内容。所有的非代码文件都保存在这个地方,比如图片、声音、属性列表和文本文件等。

1.2.1 沙盒结构

每个应用程序沙盒抖包含以下三个目录:

     1) Documents:

应用程序可以将数据存储在Documents目录中。在此目录中的文件可以被共享。其中本文中的4种数据持久化技术都涉及该目录。

     2) Library:

应用程序可以在这里存储数据。用来存放不想共享给用户的文件,需要时可以创建自己的子目录。

     3)Tmp:

Tmp目录供应用存储临时文件。在不需要这些文件时,应用要负责删除tmp中等待文件,以免占用文件系统的空间。

1.2.2 获取目录

沙盒中有上述的三个目录,获取这三个目录和相应内部的文件非常简单,只需使用C函数NSSearchPathForDirectoriesInDomains。其swift声明如下:

  1. func NSSearchPathForDirectoriesInDomains(_directory: NSSearchPathDirectory, 
  2.                                         _domainMask: NSSearchPathDomainMask,
  3.                                       _ expandTilde: Bool) -> [String] 

第一个参数指明要查找的内容,第二参数指明查找的范围,其中返回值说明返回的是数组,但是由于在沙盒中只有一个documents,或是只有一个library,那么返回的数组只有一个元素,我们只需取得第一个元素即可。

1) 获取Documents目录

  1. 1 func serarchDocumentDirectory() 
  2. 2 { 
  3. 3         let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, 
  4. 4                                                           NSSearchPathDomainMask.UserDomainMask, 
  5. 5                                                                                            true); 
  6. 6         let documentsDirectory = paths[0] as String; 
  7. 7         print(documentsDirectory); 
  8. 8 } 

2) 获取Library目录

  1. 1 func searchLibray() 
  2. 2 { 
  3. 3         let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.LibraryDirectory, 
  4. 4                                                          NSSearchPathDomainMask.UserDomainMask, 
  5. 5                                                                                          true); 
  6. 6         let libraryDirectory = paths[0] as String; 
  7. 7         print(libraryDirectory); 
  8. 8 } 

3) 获取tmp目录

获取应用程序中的临时目录的路径,要比获取Documents的目录要容易的多,有一个NSTemporaryDirectory()的函数将返回一个字符串,该字符串包含到应用程序的临时目录的完整路径。

  1. 1 func searchTmp() 
  2. 2 { 
  3. 3       let tmpDirectory = NSTemporaryDirectory(); 
  4. 4       print(tmpDirectory); 
  5. 5  } 

2. 属性列表

2.1 功能

       属性列表文件是一种xml文件,Foundation框架中的数组和字典都可以与属性列表文件互相转换,如图 1所示的转换。简单的说就是调用数组或字典的方法(read或write)进行xml文件的读或写操作

 

图 1

虽然可以将数组和字典转换为XML文件,但只有某些对象才能被放置到集合(即数组和字典)中,来实现转换。这些可被放置到集合的类有如下:

  • Array、NSArray、NSMutableArray;
  • Dictionary、NSDictionary、NSMutableDictionary;
  • NSData、NSMutableData;
  • String、NSString、NSMutableString;
  • NSNumber;
  • NSDate。

2.2 使用

实现集合和xml文件之间的转换非常简单,只是调用一下集合的写入和读取方法即可。

表 1

集合

方法(Object-C)

描述

NSArray

+arrayWithContentsOfFile(读)

静态创建工厂方法,用于从属性列表文件中读取数据,创建NSArray对象。Swift没有对应的构造器。

-initWithContentsOfFile(读)

构造器,用于从属性列表文件中读取数据,创建NSArray对象。Swift表示为convenience init?(contentsOfFile aPath:String)。

-writeToFile:atomically(写)

该方法把NSArray对象写入属性列表文件中。Swift是writeToFile。

NSDictionary

+dictionaryWithContentsOfFile(读)

静态工厂方法,从属性列表文件中读取数据,创建NSDictionary对象。Swift没有对应的构造器。

-initWithContentsOfFile(读)

构造器,从属性列表文件中读取数据,创建NSDictionary对象。Swift表示成convenience init?(contentsOfFile aPath:String)。

-writeToFile:atomically(写)

将NSDictionary对象写入到属性列表文件中,Swift是writeToFile。

注意:

         由于Swift代码中的writeToFile(,atomically)方法实际属于ObjectC的NSArray或NSDictionary类。所以要使用这个方法时,需要将Swift的Array(Dictionary)强制转换为NSArray(NSDictionary)。如:

  1. let nsArray = array as! NSArray 

2.3 实例

本实例首先是手动创建一个数组;接着将数组写入属性列表文件(file.txt);然后从属性列表文件中重新读取到数组中;最后输出验证正确性。

  1. func testPersistence() 
  2. { 
  3.         //1:获取Documents的路径,并创建file.txt的路径 
  4.         let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, 
  5.                                                           NSSearchPathDomainMask.UserDomainMask, 
  6.                                                                                            true); 
  7.         var documentsDirectory = paths[0] as String; 
  8.         documentsDirectory = documentsDirectory.stringByAppendingString("/file.txt"); 
  9.  
  10.         //2:创建swift的数组 
  11.         var array:[String] = ["1","2"]; 
  12.  
  13.         //3:将swift的数组转换为ObjectC的数组,并将数组写入属性列表文件 
  14.         let writeArray:NSArray = array as NSArray; 
  15.         writeArray.writeToFile(documentsDirectory, atomically: true); 
  16.  
  17.         //4:从属性列表文件中读取数组 
  18.         let readArray = NSArray(contentsOfFile: documentsDirectory) as! [String]; 
  19.  
  20.         //5:输出验证 
  21.         for var i = 0; i < readArray.count; i++ 
  22.         { 
  23.             print(readArray[i]); 
  24.         } 
  25. } 

3. 对象归档

3.1 简介

归档与属性列表方式不同,属性列表只有指定的一些对象才能进行持久化,而归档是任何实现了NSCopying协议的对象都可以被持久化,其中归档涉及两个类:NSKeyedArchiverNSKeyedUnarchiver。

同时对于上述三个类的归档和反归档都是采用健值对的形式编码。

3.2 实现协议

对于需要被归档化对象,需要实现NSCoding协议,该类只有两方法需要实现且只有两个方法:

表 2 Object-c语言的NSCoding协议

方法

描述

-(void)encodeWithCoder:(NSCoder *)encoder

对象进行序列化的方法,把对象信息封装在NSCoder对象中。

-(instancetype)initWithCoder:(NSCoder *)decoder

对象的反序列化方法,通过NSCoder对象获取相应数据。

其中encoder和decoder是提供给用户进行编码和解码的流对象,两个都是采用健值对的形式进行操作,并根据不同的数据类型提供不同的写入和读取的方法,如encodeInt、encodeFloat、decodeIntForKey和decodeFloatForKey等方法。

如下是myObject类实现的两个协议的程序:

  1.  1 @interface myObject : NSObject <NSCoding> 
  2.  2 { 
  3.  3     int age; 
  4.  4     float height; 
  5.  5 } 
  6.  6 @end 
  7.  7  
  8.  8 @implementation myObject 
  9.  9 -(void)encodeWithCoder:(NSCoder *)aCoder 
  10. 10 { 
  11. 11     [aCoder encodeInt:age forKey:@"age"]; 
  12. 12     [aCoder encodeFloat:height forKey:@"height"]; 
  13. 13 } 
  14. 14  
  15. 15 -(instancetype)initWithCoder:(NSCoder *)aDecoder 
  16. 16 { 
  17. 17     self = [super init]; 
  18. 18  
  19. 19     age = [aDecoder decodeIntForKey:@"age"]; 
  20. 20     height = [aDecoder decodeFloatForKey:@"height"]; 
  21. 21     return self; 
  22. 22 } 
  23. 23 @end 

3.3 归档与反归档

对需进行持久化和反持久化的对象必须实现NSCoding协议,然后才可以利用NSKeyedArchiverNSKeyedUnarchiver对象进行操作。

3.3.1 归档

归档化过程是使用NSKeyedArchiver对象归档数据,其操作步骤如下:

1) 创建NSMutableData对象:只需使用构造函数init()创建为空的对象;

2) 创建NSKeyedArchiver对象:用其构造函数initForWritingWithMutableData()创建对象;

3) 归档对象:调用NSKeyedArchiver对象的encodeObject()方法写入被归档的对象;

4) 完成操作:调用NSKeyedArchiver对象的finishEncoding()方法完成写入操作;

5) 写入文件:调用NSMutableData对象的writeToFile()写入到指定的目录下;

3.3.2 反归档

对象反归档的过程与对象归档过程类似,不同的是在创建NSMutableData对象时,需要指定目录路径,且不需要写入文件中。其操作步骤如下:

1) 创建NSMutableData对象:指定文件路径调用构造函数initWithContentsOfFile()创建对象;

2) 创建NSKeyedUnarchiver 对象:用其构造函数initForReadingWithData()创建对象;

3) 反归档对象:调用NSKeyedUnarchiver 对象的decodeObjectForKey()方法写入被归档的对象;

4) 完成操作:调用NSKeyedUnarchiver 对象的finishEncoding()方法完成写入操作;

3.4 简单示例

如对上述的myObject类进行归档化和反归档化的过程为:

  1.  1 - (void)viewDidLoad { 
  2.  2     [super viewDidLoad]; 
  3.  3 //1:获取Documents的路径,并创建file.txt的路径 
  4.  4     NSArray<NSString *> *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, true); 
  5.  5     NSString *documentsDirectory = paths[0]; 
  6.  6     documentsDirectory = [documentsDirectory stringByAppendingPathComponent:@"file.txt"]; 
  7.  7 //2:创建被保存的数据 
  8.  8     myObject *mo = [[myObject alloc] init]; 
  9.  9     [mo setAge:122]; 
  10. 10     [mo setHeight:23]; 
  11. 11  
  12. 12 //3:进行数据归档 
  13. 13     NSMutableData *encodeData = [[NSMutableData alloc] init]; 
  14. 14     NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:encodeData]; 
  15. 15     [archiver encodeObject:mo forKey:@"myObject"]; 
  16. 16     [archiver finishEncoding]; 
  17. 17     [encodeData writeToFile:documentsDirectory atomically:true]; 
  18. 18  
  19. 19 //4:进行数据反归档 
  20. 20     NSMutableData *decodeData = [[NSMutableData alloc] initWithContentsOfFile:documentsDirectory]; 
  21. 21     NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:decodeData]; 
  22. 22     myObject *dmo = [unarchiver decodeObjectForKey:@"myObject"]; 
  23. 23 [unarchiver finishDecoding]; 
  24. 24  
  25. 25 //5:验证数据 
  26. 26     NSLog(@"%d %f",[dmo age],[dmo height]); 
  27. 27 } 

3.5 编码和反编码C语言类型

NSKeyedArchiver 和NSKeyedUnarchiver类不能对structures, arrays, 和bit fields类型进行编码或反编码。

3.5.1 指针类型

由于不能归档指针类型,所以若需要只能归档指针所指向的对象。但对于C语言的字符串类型(char*)却是支持的,它比较特殊,可以使用  encodeBytes:length:forKey:方法进行归档。

3.5.2 基本数据类型的数组

一种基本的方法是一个元素一个元素归档,如"theArray[0]", "theArray[1]"这样一个个的进行归档,非常简单。

3.5.3 对象类型的数组

对于C语言的数组且元素类型是对象,那么最简单的方式是将该数组用NSArray进行封装。这样就可以进行归档了;当进行反归档时,也是获得NSArray对象,然后一个个地拆封为C语言的数组元素。

3.5.4 数据结构类型

可以将结构体的封装为一个对象,对象的每个成员是结构体的每个成员。若需要归档则先将结构体封装为OC对象,然后再归档;而反归档则是将其解析为OC对象,然后转换为C语言结构体。

iOS 数据持久化(1):属性列表与对象归档的更多相关文章

  1. iOS数据存储之属性列表理解

    iOS数据存储之属性列表理解 数据存储简介 数据存储,即数据持久化,是指以何种方式保存应用程序的数据. 我的理解是,开发了一款应用之后,应用在内存中运行时会产生很多数据,这些数据在程序运行时和程序一起 ...

  2. iOS 数据持久性存储-属性列表

    iOS上常用四种数据存取方法有: 1.属性列表 2.对象归档 3.iOS的嵌入式关系数据库(SQLite3) 4.苹果公司提供持久性共聚Core Data 由于苹果公司的沙盒机制,每个应用程序都有自己 ...

  3. iphone开发中数据持久化之——属性列表序列化(一)

    数据持久化是应用程序开发过程中的一个基本问题,对应用程序中的数据进行持久化存储,有多重不同的形式.本系列文章将介绍在iphone开发过程中数据持久化的三种主要形式,分别是属性列表序列号.对象归档化以及 ...

  4. [Objective-C] 012_数据持久化_XML属性列表,NSUserDefaults

    在日常开发中经常要对NSString.NSDictionary.NSArray.NSData.NSNumber这些基本类的数据进行持久化,我们可以用XML属性列表持久化到.plist 文件中,也可以用 ...

  5. iOS数据持久化--用户属性

    一.简介 NSUserDefaults类是一个单例类,每个程序只有一个 NSUserDefaults对象,可以用来存储用户的属性,比如自动登录时候的账号密码等小型的数据. 二.使用 1.NSUserD ...

  6. iOS 数据持久化(扩展知识:模糊背景效果和密码保护功能)

    本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

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

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

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

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

  9. iOS -数据持久化方式-以真实项目讲解

    前面已经讲解了SQLite,FMDB以及CoreData的基本操作和代码讲解(CoreData也在不断学习中,上篇博客也会不断更新中).本篇我们将讲述在实际开发中,所使用的iOS数据持久化的方式以及怎 ...

随机推荐

  1. Noah的学习笔记之Python篇:装饰器

    Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) ...

  2. Python如何读取指定文件夹下的所有图像

    (1)数据准备 数据集介绍: 数据集中存放的是1223幅图像,其中756个负样本(图像名称为0.1~0.756),458个正样本(图像名称为1.1~1.458),其中:"."前的标 ...

  3. C语言常用数学函数及其用法

    转自:http://blog.sina.com.cn/s/blog_8b5a0d0001011779.html 三角函数:(所有参数必须为弧度)  1.acos 函数申明:acos  (double ...

  4. js页面传参数时,参数值包含特殊字符的处理

    js页面传参数时,参数值包含特殊字符应该怎么处理,解决方法就是利用js的escape函数,这个函数在解决中文乱码等方面应用的比较广泛.推荐使用. 工作中遇到的小问题,一个页面中通过window.sho ...

  5. MySQL FEDERATED引擎使用示例, 类似Oracle DBLINK

    原文地址:http://it.dataguru.cn/article-3352-1.html 摘要: 本地MySQL数据库要访问远程MySQL数据库的表中的数据, 必须通过FEDERATED存储引擎来 ...

  6. httpclient 超时设置

    最近项目客户反应超时经常出现:现已经总结超时设置: 使用是apache的HttpClient: DefaultHttpClient:请求超时httpclient.getParams().setPara ...

  7. Solr4.4的安装与配置

    最近准备用Solr搭建项目,所以对其作了一些了解,我采用的是Solr4.4版本:这个版本的Solr相对于以前的版本改变很大,这里记一下自己安装与配置的过程. 网上很多关于Solr的教程都很老了,很多教 ...

  8. 别再说“我已经努力了”,你的“努力”一文不值!

    有次,让一个研究生男收集一份资料,快下班了问结果,竟然毛也没有.见我要怒,他慷慨激昂地说:"我已经很努力找了,但真的查不到." 作为主管,"我已经努力"这话我不 ...

  9. URAL1079

    Problem E Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 32768/16384K (Java/Other) Total Sub ...

  10. NIOS中双CPU系统的构建

    首先构建SOPC系统,先分别添加两个CPU,分别命名为CPU1和CPU2,设置如下图,其中CPU1运行VGA的乒乓游戏,CPU2运行音乐,这里为了简单,音乐用LED来表示. 这里CPU1选择是中等容量 ...