IOS数据本地存储的四种方式--
注:借鉴于:http://blog.csdn.net/jianjianyuer/article/details/8556024
在IOS开发过程中,不管是做什么应用,都会碰到数据保存问题。将数据保存到本地,能够让程序更加流畅,不会出现让人厌恶的菊花状,使得用户的体验更好。下面是介绍数据保存的方式
第一、NSKeyedArchiver:采用归档的形式来保存数据。(归档——解档)———大量数据和频繁读写不合适使用
1、归档器的作用是将任意的对象集合转换为字节流。这听起来像是NSPropertyListSerialization类采用的过程,但是它们之间有一个重要的区别。属性列表序列化只能转换一个有限集合的数据类型(大多是数量类型),而归档可以转换任意的OC对象、数据类型、数组、结构、字符串以及更多其他类型。
2、Foundatio框架支持两种归档器。顺序归档和基于键的归档。基于键的归档器更加灵活,是应用程序开发中推荐使用的归档器 。
3、一个面向对象程序在运行的时候,一般都创建了一个复杂的对象关系图,经常需要把这样一个复杂的对象关系图表示成字节流,这样的过程叫做 Archiving.
4、而当从字节流中重新恢复对象关系图的过程叫做unarchive。
5、NSCoder是archivie字节流的抽象类。
6、对一个对象归档需要满足的条件是:该对象的类必须实现NSCoding协议
归档、
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
-( int )create:(Note *)model { NSString *homeDictionary = NSHomeDirectory (); NSString *path = [homeDictionary stringByAppendingPathComponent:FILE_NAME]; NSFileManager *fileManager = [ NSFileManager defaultManager]; BOOL isexists = [fileManager fileExistsAtPath:path]; NSMutableArray *array = [[ NSMutableArray alloc] init]; [array addObject:model]; //archive归档 NSMutableData *theData = [ NSMutableData data]; NSKeyedArchiver *archiver = [[ NSKeyedArchiver alloc] initForWritingWithMutableData:theData]; [archiver encodeObject:array forKey:ARCHIVE_KEY]; [archiver finishEncoding]; [theData writeToFile:path atomically: YES ]; // [array writeToFile:path atomically:YES]; return 0; } |
解档、
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
-( NSMutableArray *)findAll { NSString *homeDictionary = NSHomeDirectory (); NSString *path = [homeDictionary stringByAppendingPathComponent:FILE_NAME]; NSMutableArray *listData = [[ NSMutableArray alloc] init]; NSData *theData = [ NSData dataWithContentsOfFile:path]; if ([theData length]>0) { NSKeyedUnarchiver *archiver = [[ NSKeyedUnarchiver alloc] initForReadingWithData:theData]; listData = [archiver decodeObjectForKey:ARCHIVE_KEY]; [archiver finishDecoding]; } return listData; } |
第二、NSUserDefaults
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
//自动登陆用到的 +( id )configForKey:( NSString *)key { NSUserDefaults * defaults = [ NSUserDefaults standardUserDefaults]; return [defaults objectForKey:key]; } //写入内容 +( void )setLoginConfig:( id )value forKey:( NSString *)key { NSUserDefaults *user = [ NSUserDefaults standardUserDefaults]; [user setObject:value forKey:key]; [user synchronize]; //及时强制写入 } //读出内容 +( NSString *)getLoginConfig:( NSString *)key { NSString *s = [Globle configForKey:key]; if (s== nil ) { return @ "" ; } return s; } |
第三、write写入磁盘
第一步:获得文件即将保存的路径:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);//使用C函数NSSearchPathForDirectoriesInDomains来获得沙盒中目录的全路径。该函数有三个参数,目录类型、he domain mask、布尔值。其中布尔值表示是否需要通过~扩展路径。而且第一个参数是不变的,即为NSSearchPathDirectory 。在IOS中后两个参数也是不变的,即为:NSUserDomainMask 和 YES。
NSString *ourDocumentPath =[documentPaths objectAtIndex:0];
还有一种方法是使用NSHomeDirectory函数获得sandbox的路径。具体的用法为:
NSString *sandboxPath = NSHomeDirectory();
// Once you have the full sandbox path, you can create a path from it,但是不能在sandbox的本文件层上写文件也不能创建目录,而应该是此基础上创建一个新的可写的目录,例如Documents,Library或者temp。
NSString *documentPath = [sandboxPath
stringByAppendingPathComponent:@"Documents"];//将Documents添加到sandbox路径上,具体原因前面分析了!
这两者的区别就是:使用NSSearchPathForDirectoriesInDomains比在NSHomeDirectory后面添加Document更加安全。因为该文件目录可能在未来发送的系统上发生改变。
第二步:生成在该路径下的文件:
NSString *FileName=[documentDirectory stringByAppendingPathComponent:fileName];//fileName就是保存文件的文件名
第三步:往文件中写入数据:
[data writeToFile:FileName atomically:YES];//将NSData类型对象data写入文件,文件名为FileName
最后:从文件中读出数据:
NSData data=[NSData dataWithContentsOfFile:FileName options:0 error:NULL];//从FileName中读取出数据
第四、SQLite数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
@interface BaseViewController () { sqlite3 *sqlDataBase; } @end @implementation BaseViewController - ( id )initWithNibName:( NSString *)nibNameOrNil bundle:( NSBundle *)nibBundleOrNil { self = [ super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if ( self ) { // Custom initialization } return self ; } - ( void )viewDidLoad { [ super viewDidLoad]; if ([ self createOrOpen:@ "test.db" ]) { // [self createUserTable:sqlDataBase]; // [self insertMBkey:nil]; NSMutableArray *s = [ NSMutableArray new ]; [ self GetList:s]; NSLog (@ "%@" ,s); } else { NSLog (@ "FAIL" ); } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
|
/** *该函数主要打开数据库myDataBase.sql,如果该数据库不存在,则进行创建 *打开或者创建成功返回yes,否则返回false,参数dbName是数据库的名称 **/ -( BOOL )createOrOpen:( NSString *)dbName { //获取用户域覆径信息 NSArray *paths = NSSearchPathForDirectoriesInDomains ( NSDocumentationDirectory , NSUserDomainMask , YES ); NSString *documentsDirectory = [paths objectAtIndex:0]; /** *Users/admin/Library/Application Support/iPhone Simulator/7.1/Applications/8E23557E-AAA6-471A-AAFE-E036BF1B7E4C/Library/Documentation *判断用户域是否有数据库dbNmae */ NSString *path = [documentsDirectory stringByAppendingPathComponent:dbName]; NSFileManager *fileManageer = [ NSFileManager defaultManager]; //如果用户域内有该数据库,则返回yes,否则返回NO BOOL find = [fileManageer fileExistsAtPath:path]; if (find) //对找到进行处理,如果找到了,并且打开了,则返回yes { //打开该数据库,如果打开失败,则返回NO,否则返回yes if (sqlite3_open([path UTF8String], &sqlDataBase)!= SQLITE_OK) { //关闭sqlDataBase,实际是释放了它 sqlite3_close(sqlDataBase); return NO ; } return YES ; } NSLog (@ "%d" ,sqlite3_open([path UTF8String], &sqlDataBase)); //创建数据库,创建返回yes,并且打开数据库,否则返回NO if (sqlite3_open([path UTF8String], &sqlDataBase)==SQLITE_OK) { return YES ; } else { //关闭sqlDataBase,实际是释放了它 sqlite3_close(sqlDataBase); return NO ; } return NO ; } //在打开的数据库中创建表,其中sqldb为成功打开的数据库的sqlite3对象 -( BOOL )createUserTable:(sqlite3 *)sqlDataBas { //设置sql语句 char *sql = "create table user(id integer primary key, name text, address text, imageData BLOB, imageLen integer)" ; sqlite3_stmt *statement; //这个相当于ODBC的Command对象,用于保存编译好的SQL语句 //进行预处理,预处理失败返回NO if (sqlite3_prepare_v2(sqlDataBase, sql, -1, &statement, nil )!=SQLITE_OK) { return NO ; } //预处理成功,进行执行创建操作 int success = sqlite3_step(statement); sqlite3_finalize(statement); if (success !=SQLITE_DONE) { return NO ; } return YES ; } //向表中插入数据 -( void )insertMBkey:( NSString *)key { BOOL isOK = NO ; sqlite3_stmt *statement; static char *sql = "INSERT INTO user VALUES ('1', 'Bill', '河南', 'ssss','2')" ; int success = sqlite3_prepare_v2(sqlDataBase, sql, -1, &statement, NULL ); if (success !=SQLITE_OK) { isOK = NO ; } else { sqlite3_bind_text(statement, 1, [key UTF8String], -1, SQLITE_TRANSIENT); success = sqlite3_step(statement); sqlite3_finalize(statement); } if (success ==SQLITE_ERROR) { isOK = NO ; } else { isOK= YES ; } return ; } //查询数据 -( void )GetList:( NSMutableArray *)KeysList { BOOL isOK = NO ; sqlite3_stmt *statement; static char *sql = "select id,address from user" ; int success = sqlite3_prepare_v2(sqlDataBase, sql, -1, &statement, NULL ); if (success !=SQLITE_OK) { isOK = NO ; } else { //查询结果集中一条一条地遍历所有记录,这里的数字对应的时列值 while (sqlite3_step(statement)==SQLITE_ROW) { int kid = sqlite3_column_int(statement, 0); char *key = ( char *)sqlite3_column_text(statement, 1); UserInfo *userModel = [[UserInfo alloc] init]; userModel.userId =kid; if (key) { userModel.userAddress = [ NSString stringWithUTF8String:key]; } [KeysList addObject:userModel]; sqlite3_finalize(statement); } NSLog (@ "%@" ,KeysList); if (success==SQLITE_ERROR) { isOK = NO ; } else { isOK = YES ; } return ; } } |
IOS数据本地存储的四种方式--的更多相关文章
- ios页面间传递参数四种方式
ios页面间传递参数四种方式 1.使用SharedApplication,定义一个变量来传递. 2.使用文件,或者NSUserdefault来传递 3.通过一个单例的class来传递 4.通过Dele ...
- [转载]-win7启动本地MongoDB的四种方式
2016年04月07日 09:52:34 cherry__cheng 阅读数:19451 标签: win7启动本地MongoDB的四种方式快速启动本地mongodb 更多 个人分类: mongodb& ...
- android 数据存储的四种方式.
Android系统一共提供了四种数据存储方式.分别是:SharePreference.SQLite.Content Provider和File.由于Android系统中,数据基本都是私有的的,都是存放 ...
- IOS音频1:之采用四种方式播放音频文件(一)AudioToolbox AVFoundation OpenAL AUDIO QUEUE
本文转载至 http://blog.csdn.net/u014011807/article/details/40187737 在本卷你可以学到什么? 采用四种方法设计应用于各种场合的音频播放器: 基于 ...
- ASP.NET MVC之控制器传递数据到视图的四种方式
前奏 1. 在新建项目中的Models文件下,新建Products类: public class Products { public int Id { get; set; } public strin ...
- C#批量插入数据到Sqlserver中的四种方式
我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...
- C#_批量插入数据到Sqlserver中的四种方式
先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...
- C#批量插入数据到Sqlserver中的四种方式 - 转
先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...
- 实现web数据同步的四种方式
http://www.admin10000.com/document/6067.html 实现web数据同步的四种方式 1.nfs实现web数据共享 2.rsync +inotify实现web数据同步 ...
随机推荐
- Linux 查看文件
1: cat file_full_name 这种方法适合查看小文件 cat /etc/services cat -n file_full_name -n 可以加行号! 2: tac file_ful ...
- Linux菜鸟之路[4]-cal,date,bc,echo $LANG,man
由于前四天一直在看鸟哥的linux书本的计算机的一些基础知识,今天才接触基本的命令,从今天起每天记录一下自己的linux学习过程. cal:日历 cal: cal 2015:列出2015年所有日历 c ...
- 害人的VS2008,manifest导致“应用程序配置不正确,应用程序未能启动”
在VC++2008的项目中,如何显示地指定要使用的C++库的版本? 开发环境:VS2008 SP1 + Win2003 SP2 因为我的VS2008安装了SP1补丁,所以有了9.0.3 ...
- 有关VS2008制作安装包时遇到的问题详解
公司最近要做一个安装包,然而在做的时候遇到好多问题,这里我一一记录下来 一.先用VS2008建一个Setup项目,添加你需要打包的文件,这里我就不具体介绍了,网上一搜都好多,这时我们一般都需要在安装前 ...
- ListView中响应item的点击事件并且刷新界面
---恢复内容开始--- 最近在在实现listview功能中遇到了这个问题: 点击事件写在了adapter的item中,不知道如何在listview的点击事件中更新数据的显示: 总结:1.要使用not ...
- 简单天气应用开发——自定义TableView
顺利解析JSON数据后,天气数据已经可以随意提取了,现在要做的就是建立一个简单的UI. 实况信息较为简单,几个Lable就可以解决.主要是七天天气预报有点麻烦,那是一个由七个字典构成的数组,需要提取出 ...
- c++ primer plus 习题答案(5)
p333.7 #include<iostream> #include<cstring> #include<cstdlib> using namespace std; ...
- C++内置类型对象之间的转换
C++定义了一组内置类型对象之间的标准转换,在必要时它们被编译器隐式地应用到对象上. 隐式类型转换发生在下列这些典型情况下. 1. 在混合类型的算数表达式中 规则:在这种情况下最宽的数据类型成为目标转 ...
- JavaEE学习之类加载器
类装载子系统 在JAVA虚拟机中,负责查找并装载类型的那部分被称为类装载子系统. JAVA虚拟机有两种类装载器:启动类装载器和用户自定义类装载器.前者是JAVA虚拟机实现的一部分,后者则是Java程序 ...
- Lucence.net索引技术 一
1.建立索引 为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory.下面我们分别介绍一下 ...