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 | /** *该函数主要打开数据库myDataBase.sql,如果该数据库不存在,则进行创建 *打开或者创建成功返回yes,否则返回false,参数dbName是数据库的名称 **/ -( BOOL )createOrOpen:( NSString *)dbName { //获取用户域覆径信息 NSArray *paths = NSSearchPathForDirectoriesInDomains ( NSDocuemntDirectory , NSUserDomainMask , YES );<em id = "__mceDel" > 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 ; } } </em> |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· 深入理解Mybatis分库分表执行原理
· 使用 Dify + LLM 构建精确任务处理应用