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数据同步 ...
随机推荐
- MYSQL this function has none of deterministic no sql ......错误
This function has none of DETERMINISTIC, NO SQL解决办法 创建存储过程时 出错信息: ERROR 1418 (HY000): This function ...
- TCP/IP笔记 三.运输层(2)——TCP 流量控制与拥塞控制
TCP 的流量控制与拥塞控制可以说是一体的.流量控制是通过滑动窗口实现的,拥塞避免主要包含以下2个内容: (1)慢开始,拥塞避免 (2)快重传,快恢复 1.流量控制——滑动窗口 TCP采用大小可变的滑 ...
- 动态子类化CComboBox以得到子控件EDIT及LISTBOX
动态子类化CComboBox以得到子控件EDIT及LISTBOX Joise.LI写于2004-4-6 ComboBox是比较常用的一个控件,有三种样式:CBS_SIMPLE(简单),CBS_DROP ...
- 51nod 1239 欧拉函数之和(杜教筛)
[题目链接] https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1239 [题目大意] 计算欧拉函数的前缀和 [题解] 我们 ...
- WCF 双工通信
注释:本学习是参考Artech大神的资料: 在WCF 实现双工通信 在这里我就不介绍双工通信的概念了,我写博客的目的是检测自己掌握情况,看我wcf通信后,觉得纸上得来终觉浅,绝知此事要躬行. 我使用的 ...
- Windows Server 2012 R2 服务器管理器介绍和配置使用
1. 服务管理器是用于管理系统服务的管理工具.一般常用于windows系统,使用这个工具你可以启动.停止服务:设置服务是自动.手动启动或禁用:查看某个服务的相关信息:设置服务以什么用户启动等等(一般包 ...
- POJ 3268 Silver Cow Party 正反图最短路
题目:click here 题意: 给出n个点和m条边,接着是m条边,代表从牛a到牛b需要花费c时间,现在所有牛要到牛x那里去参加聚会,并且所有牛参加聚会后还要回来,给你牛x,除了牛x之外的牛,他们都 ...
- gsoap 超时(timeout)设置
参考:http://www.cs.fsu.edu/~engelen/soapdoc2.html#tth_sEc19.19 gsoap就不用介绍了,是一个c/c++编写的可用于服务端与客户端的连接工具. ...
- [LeetCode]题解(python):005-Longest Palindromic Substring
题目来源: https://leetcode.com/problems/longest-palindromic-substring/ 题意分析: 这道题目是输入一段不超过1000的字符串,输出最长的回 ...
- Python collections.defaultdict 笔记
其实defaultdict 就是一个字典,只不过python自动的为它的键赋了一个初始值.这也就是说,你不显示的为字典的键赋初值python不会报错,看下实际例子. 比如你想计算频率 frequenc ...