持久化(Persistence)

持久化(Persistence)意思就是当你退出app的时候它还会存在。NSUserDefaults就是一个非常简单的持久化方案,不过这有限制,它只能是很小的东西,通常是些用户选项。

如何把那些大数据的东西持久化?

第一个方法,把东西持久化的第一个简单的方式有点像用NSUserDefaults里的property list来实现的进化版,property list是我们自定义的一个概念,是NSArray、NSDictionary、NSNumber、NSString、 NSDate和NSData的组合。所有以上这些都有API可以用来保存,NSUserDefaults也有些API可以。

NSData、NSArray和NSDictionary里还有很重要的方法writeToURL:atomically:,这个方法就是把一个array写到一个文件系统中URL表示的地方,atomically就是如果文件已经存在,它会把文件移到一边,然后写到一个新的文件,关掉这个新的文件。实际上就是写到一个临时命名的文件,然后关掉,把另一个移走,有点原子化操作的感觉,不能写到一半就停下来。writeToURL之后,为了把东西取回来,可以用initWithContentsOfURL或者dataWithContentsOfURL。这些读写方法,不管是发送到NSData或者NSArray或者NSDictionary,就是想让一个相同类型的对象去读回来,它的内部可以就是些property list的东西。

还有另一个类叫做NSPropertyListSerialization,它所做的事情就是把property list转化成NSData,反之亦然。这样它可以将property list转化成一堆二进制数,然后就可以写到磁盘上,或储存到网络。也可以通过网络读取一堆二进制数再通过NSPropertyListSerialization把它们转化回property list。

关于存储的另外一个方法就是通过对象的映像图(arbitrary graphs)来进行归档对象(Archiving Objects)的保存。

把东西存储到文件系统当中。

然后是SQLite

关于持久化存储的重头部分就是Core Data,这是在SQL上层的一个面向对象的数据库机制。

Archiving

在做对象图归档的时候有很多陷阱,归档很适合做循环图。Archiving能发现指针实际所指的对象或者指针相互指着,然后当unarchives的时候又恢复那个指针。但你要考虑清楚来使你构建的对象图有意义,最好的例子可能是在xcode里面建立的view层级。

当从对象库中拖一些东西到屏幕上,就是在实例化UIView,实例化UIViewController,它们都是generic的,所以才需要去inspector面板来改变它们的类。

基本上就是在这个图里面的对象都必须实现NSCoding这个protocol,然后这个protocol里面有两个重要方法:

- (void)encodeWithCoder:(NSCoder *)coder;
- initWithCoder:(NSCoder *)coder;

第一个是把自己放进archive,第二是把你从archive中取出来用的。这就是viewController出现在storyboard时不用调用它们的指定初始化的原因,因为它们用了这套初始化。这套归档系统在对它们做alloc initWithCoder,因为它们之前用encodeWithCoder把自己保存起来了。在UIView里没有调用initWithFrame,而是用frame对应的encodeWithCoder和initWithCoder来代替。

- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeFloat:scale forKey:@“scale”];
[coder encodeCGPoint:origin forKey:@“origin”];
[coder encodeObject:expression forKey:@“expression”];
}

必须保证initWithCoder和encodeWithCoder是相对应的。

- initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
scale = [coder decodeFloatForKey:@“scale”];
expression = [coder decodeObjectForKey:@“expression”];
origin=[coderdecodeCGPointForKey:@“origin”]; //notethatorderdoesnotmatter
}

怎么来实现这些呢?NSKeyedArchiver中的类方法:

+ (NSData *)archivedDataWithRootObject:(id <NSCoder>)rootObject;

可以传递一个根对象,比如在storyboard里面的根对象就可能是顶层的view controller。你要做的就是确保里面所有的对象都实现NSCoder协议。

NSKeyedUnarchiver中的类方法:

+ (id <NSCoder>)unarchiveObjectWithData:(NSData *)data;

这正好相反,你提供一个已经归档的NSData,然后返回被encode的根对象。

id <NSCoder> object = ...;
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object];
id <NSCoder> dup = [NSKeyedArchiver unarchiveObjectWithData:data];

如果有一个对象,通过第二行将得到关于这个对象的NSData。

如果encode一个view使它的super view被归档,你会被拒绝,除非它处于正确的层级,如果它在顶部它会被拒绝,但如果在内部,就会执行。

File System

ios是基于Unix的,底层都是Unix的文件系统,这里有文件系统保护,不可能看到所有的东西,而且也不能随意的写入。

只能在sandbox中做写入,为什么?为了安全。当在设备上删除app时,也会删除所有相关的数据。通过在sandbox中进行写操作,所有应用程序的东西不管是用户创建的还是应用程序自己在sandbox里面创建的一旦移除,所有的都会被移除。

sandbox到底是什么?这里面有应用程序的bundle目录,应用程序不是单独的大的二进制文件,它实际上是一个目录,里面有可执行程序、二进制文件、storyboard及拖进来的图片,所有东西都在里面,这就是应用程序的bundle。sandbox里的目录本身是不可写的,不能在目录里写入东西。这基本上就是一个用xcode创建的app的只读副本。documents目录是sandbox中的一个重要目录,这些地方是用来存储那些被用户视为是自己的文档的。还有一个缓存目录,这里都是一些我们写出来的东西,用户一般不会认为这些是文档,而且这些文档的存在都很短暂,没有了也不会影响到用户。documentation里的关键东西是NSSearchPathDirectory。

如何才能得到这些目录,如何得到这些目录的URL?如果想在application目录中写入,但又不能写入,那么要做的就是将application包里面的东西拷贝到sandbox中任意一个可写的地方然后在那里写入。如果你想将一个数据库连接到你的app,或写入那些数据库,得将它们拷贝出来,无论是拷到文档目录,或是缓存目录,总之是可以写入了。

如何搞到这些目录的路径呢?使用这个方法:

- (NSArray *)URLsForDirectory:(NSSearchPathDirectory)directory
inDomains:(NSSearchPathDomainMask)domainMask; //NSUserDomainMask

NSURL中有个API可以获得一个URL的清单,但得传入想要的目录类型,譬如文档目录、缓存目录。以上方法和NSURL的方法,它们返回一个路径的array,所以当我请求缓存目录时,将得到一个URL的array,或是路径字符串的数组。

NSFileManager为文件系统提供实用操作,这不是用来读写它们自身文件的类。你可以用它来找出文件到底有多大,删除那些陈旧的需要被踢出的缓存文件,也可以用它来找出譬如当应用程序启动时,缓存里面都有哪些文件。它是线程安全的,只要不在两个不同的线程中使用同一个实例。

NSString也有一些文件系统有关的东西,特别是制作路径,一般用NSURL来指定一个链接,有时会用字符串来构建URL。

- (NSString *)stringByAppendingPathComponent:(NSString *)component;

这可以在一个路径中添加内容。还可以把字符串的内容写到文件里去,必须要指定用哪种编码,譬如ASCII、ISOLatin1,

- (BOOL)writeToFile:(NSString *)path
atomically:(BOOL)flag
encoding:(NSStringEncoding)encoding //e.g.ASCII,ISOLatin1,etc.
error:(NSError **)error;

也可以从文件读取string:

- (NSString *)stringWithContentsOfFile:(NSString *)path
usedEncoding:(NSStringEncoding *)encoding
error:(NSError **)error;

SQLite

SQLite是指SQL文件保存在单一一个文件里,存储在一个单一的文件中,它速度很快,只占用很小的内存。它基于事务处理,是真正的SQL。这不是基于服务器的SQL,而是基于文件的,所以它是并发性的。如果app中有两个线程,都要写入到SQL数据库中,这可以正常运行。但它只是做简单的锁线程和并发。

以下就是它的API:

intsqlite3_open(constchar*filename,sqlite3**db); //get a database into db
int sqlite3_exec(sqlite3 *db, // execute SQL statements
const char *sql,
int (*callback)(void *, int, char **, char **),
void *context,
char **error);
int mycallback(void *context,int count,char **values,char **cols); //data returned
int sqlite3_close(sqlite3 *db); // close the database

当你打开SQL文件时,你会得到一个SQL数据库指针,然后要执行SQL语句。向数据库递交你的SQL语句,一些SQL语句就会回调然后在一张表中将你请求的数据返回给你,返回的也可能是error。回调函数通常是这样的格式:

int mycallback(void *context,int count,char **values,char **cols);

然后就可以关闭了。你要做的就是第三行const char *sql,这是执行SQL语句的地方。

from:http://www.cnblogs.com/geory/archive/2013/03/11/2953294.html

iOS应用开发之Persistence持久化[转]的更多相关文章

  1. iOS多线程开发之GCD(中篇)

    前文回顾: 上篇博客讲到GCD的实现是由队列和任务两部分组成,其中获取队列的方式有两种,第一种是通过GCD的API的dispatch_queue_create函数生成Dispatch Queue:第二 ...

  2. iOS多线程开发之NSOperation - 快上车,没时间解释了!

    一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强 ...

  3. iOS游戏开发之UIDynamic

    iOS游戏开发之UIDynamic 简介 什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象 ...

  4. iOS多线程开发之NSOperation

    一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强 ...

  5. iOS多线程开发之GCD(死锁篇)

    上篇和中篇讲解了什么是GCD,如何使用GCD,这篇文章将讲解使用GCD中将遇到的死锁问题.有兴趣的朋友可以回顾<iOS多线程开发之GCD(上篇)>和<iOS多线程开发之GCD(中篇) ...

  6. iOS多线程开发之GCD(中级篇)

    前文回顾: 上篇博客讲到GCD的实现是由队列和任务两部分组成,其中获取队列的方式有两种,第一种是通过GCD的API的dispatch_queue_create函数生成Dispatch Queue:第二 ...

  7. iOS高效开发之Xcode应用插件

    前言:本文非原创 文章摘自 www.cocoachina.com/industry/20130918/7022.html    古人云“工欲善其事必先利其器”,打造一个强大的开发环境,是立即提升自身战 ...

  8. iOS网络开发之AFNetworking

    概述 AFNetworking是一个非常受欢迎的轻量级的iOS.Mac OS X网络通信类库.它建立在NSURLConnection.NSOperation以及其技术的基础上,有着精心设计的模块结构和 ...

  9. iOS 多线程开发之OperationQueue(二)NSOperation VS GCD

    原创Blog.转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS SDK具体解释专栏 http://blog.csdn.net/column/details/huang ...

随机推荐

  1. 使用wifi网卡笔记3---工具wpa_supplicant(STA模式)

    1.  wpa_supplicant介绍 supplicant是恳求者的意思,是wpa的发起者,是发送认证请求的设备(手机),手机--AP--认证服务器,可用于上述4种"认证/加密" ...

  2. 【学习笔记】LCT link cut tree

    大概就是供自己复习的吧 1. 细节讲解 安利两篇blog: Menci 非常好的讲解与题单 2.模板 把 $ rev $ 和 $ pushdown $ 的位置记清 #define lc son[x][ ...

  3. 【BZOJ】1012: [JSOI2008]最大数maxnumber /【洛谷】1198(线段树)

    Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插 ...

  4. 移动终端App测试点归纳

    以下所有测试最后必须在真机上完整的执行. 1 安装.卸载测试 1.1 在真机上.第三方软件(xy苹果助手.91.安卓助手)的安装与卸载 1.2 安装在手机卡上 或 SD卡上 (不同的IOS和安卓版本) ...

  5. quartz报错 Couldn't retrieve job because the BLOB couldn't be deserialized: null

    今天线上添加定时任务之后 定时任务查询页面报出如上错误, 原因有两点 1.org.quartz.jobStore.useProperties = true 这个属性的意思存储的JobDataMaps是 ...

  6. Tkinter Spinbox

    Python - Tkinter Spinbox: Spinbox小部件是一个标准的Tkinter的Entry小窗口部件的变体,它可以用来选择从一个固定的值.   Spinbox小部件是一个标准的Tk ...

  7. openLayers 3 之入门

    openLayers 3 之入门 openlayer是web GIS客户端开发提供的javascript类库,也是开源框架,可以加载本地数据进行展示地图 1.下载相关引用的js.css文件 2.类似于 ...

  8. Android MVP模式简单易懂的介绍方式 (一)

    Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 最近正在研究Android的MVP模式 ...

  9. VS2017更新后 在WIN7上找不到 stdio.h等的问题

    项目->属性->配置属性->常规->windows SDK版本.将其换成你现在的版本即可解决问题,如果不行就重新下个最新版SDK,如WIN10的.

  10. input子系统分析之三:驱动模块

    内核版本:3.9.5 本节将以even handler来分析设备的注册和打开的过程,分析之前不妨回顾一下上节介绍的数据结构. 结合前两节分析可知,input子系统分为3层,最上一层是event han ...