持久化(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. Druid.io系列(二):基本概念与架构

    原文链接:  https://blog.csdn.net/njpjsoftdev/article/details/52955788 在介绍Druid架构之前,我们先结合有关OLAP的基本原理来理解Dr ...

  2. StringsUtil字符串工具类---灵活截取

    package com.js.ai.modules.pointwall.interfac; import javax.print.attribute.standard.MediaName; publi ...

  3. 查看Unix/Linux的CPU个数和内存大小,系统位数(转载)

    一.AIX 1.查看CPU数: (1) smtctl 从AIX5.3起,对于power5的机器,系统引入了SMT(Simultaneousmulti-threading)的功能,其允许两个处理线程在同 ...

  4. python‘s third day for me 字符串方法

    基 础 数 据 类 型 初 始   int  运算.+  -  *  /  **  %... bool: 判断,真假,作为条件. str:  存储少量的数据.操作简单,便于传输. list:  列表[ ...

  5. [Python] Request module

    http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

  6. spring-boot-actuator健康监控

    #健康监控 management.security.enabled=false health.mail.enabled =false http://localhost:54001/autoconfig ...

  7. 让低版本IE支持Html5的新语义标签

    HTML5能为我们做的事儿很多,最为可口的就是语义化标签的应用,如果你已经在Chrome或者其他支持HTML5的浏览器上用过它的牛x,那这篇文章对你一定有用,因为现在你也可以在IE上用到HTML5. ...

  8. 2017年Java学习总结

    2017年Java学习      Java,是我学习的第三种计算机编程语言,刚拿到这本教材时,我被它的厚度与书中字体的密集程度吓了一跳,不过在学习过程中,有Python,C语言的学习基础上,加上老师的 ...

  9. 01 lucene基础 北风网项目培训 Lucene实践课程 索引

    在创建索引的过程中IndexWriter会创建多个对应的Segment,这个Segment就是对应一个实体的索引段.随着索引的创建,Segment会慢慢的变大.为了提高索引的效率,IndexWrite ...

  10. Renderer.materials 和sharedMaterials一些用法上的区别

    Not allowed to access Renderer.materials on prefab object. Use Renderer.sharedMaterials insteadUnity ...