iOS 数据保存几种方式总结_苹果ld都会保留那些数据-程序员宅基地

技术标签: image  database  sqlite  sandbox  ios  数据库  

在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题。将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好。下面介绍一下数据保存的方式:
1.NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码。例如对Possession对象归档保存。
定义Possession:
@interface Possession:NSObject<NSCoding>{//遵守NSCoding协议
       NSString *name;//待归档类型
}
@implementation Possession
-(void)encodeWithCoder:(NSCoder *)aCoder{
            [aCoder encodeObject:name forKey:@"name"];
}
-(id)initWithCoder:(NSCoder *)aDecoder{
            name=[[aDeCoder decodeObjectforKey:@"name"] retain]; return self;
}
归档操作:
如果对Possession对象allPossession归档保存,只需要NSCoder子类NSKeyedArchiver的方法archiveRootObject:toFile: 即可。

NSString *path = [self possessionArchivePath];
[NSKeyedArchiver archiveRootObject:allPossessions toFile: path ]
解压操作:

同样调用NSCoder子类NSKeyedArchiver的方法unarchiveRootObject:toFile: 即可  
allPossessions = [[NSKeyedUnarchiver unarchiveObjectWithFile:path] retain];

缺点:归档的形式来保存数据,只能一次性归档保存以及一次性解压。所以只能针对小量数据,而且对数据操作比较笨拙,即如果想改动数据的某一小部分,还是需要解压整个数据或者归档整个数据。
2.NSUserDefaults:用来保存应用程序设置和属性、用户保存的数据。用户再次打开程序或开机后这些数据仍然存在。NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。如果要存储其他类型,则需要转换为前面的类型,才能用NSUserDefaults存储。具体实现为:
保存数据:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
NSString *name =@”default string“;
[defaults setObject:firstName forKey:@"name"];
  //获得UIImage实例

UIImage *image=[[UIImage alloc]initWithContentsOfFile:@"photo.jpg"];

NSData *imageData = UIImageJPEGRepresentation(image, 100);//UIImage对象转换成NSData

[defaults synchronize];//用synchronize方法把数据持久化到standardUserDefaults数据库
读取数据:

NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
NSString *name = [defaults objectForKey:@"name"];//根据键值取出name
NSData *imageData = [defaults dataForKey:@"image"];
UIImage *Image = [UIImage imageWithData:imageData];//NSData转换为UIImage
3. 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中读取出数据
4. SQLite:采用SQLite数据库来存储数据。SQLite作为一中小型数据库,应用ios中,跟前三种保存方式相比,相对比较复杂一些。还是一步步来吧!
第一步:需要添加SQLite相关的库以及头文件:在项目文件的Build Phases下,找到Link Binary Library(ies),添加libsqlite3.0.dylib(libsqlite3.dylib与前者的区别暂时不知,两者应该差不多);在项目文件中头文件或者源文件中添加头文件#import "/usr/include/sqlite3.h"
第二步:开始使用SQLite:
NSArray *documentsPaths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask , YES);
NSString *databaseFilePath=[[documentsPaths objectAtIndex:0] stringByAppendingPathComponent:@"mydb"];
//上面两句已经比较熟悉了吧! 
//打开数据库
if (sqlite3_open([databaseFilePath UTF8String], &database)==SQLITE_OK) { 
        NSLog(@"sqlite dadabase is opened."); 
}
else{ return;}//打开不成功就返回
在打开了数据库的前提下,如果数据库没有表,那就开始建表了哦!
char *error; 
const char *createSql="create table(id integer primary key autoincrement, name text)";
if (sqlite3_exec(database, createSql, NULL, NULL, &error)==SQLITE_OK) { 
        NSLog(@"create table is ok."); 
}
else
{
       NSLog(@"error: %s",error);
       sqlite3_free(error);//每次使用完毕清空error字符串,提供给下一次使用
} 
建表完成之后,就开始插入记录:

const char *insertSql="insert into a person (name) values(‘gg’)"; 
if (sqlite3_exec(database, insertSql, NULL, NULL, &error)==SQLITE_OK) { 
        NSLog(@"insert operation is ok."); 
}

else
{
       NSLog(@"error: %s",error);
       sqlite3_free(error);//每次使用完毕清空error字符串,提供给下一次使用
} 
下一步,查询记录:

const char *selectSql="select id,name from a person"; 
sqlite3_stmt *statement; 
if (sqlite3_prepare_v2(database,selectSql, -1, &statement, nil)==SQLITE_OK) { 
        NSLog(@"select operation is ok."); 
}
else
{
       NSLog(@"error: %s",error);
       sqlite3_free(error);
} 
while(sqlite3_step(statement)==SQLITE_ROW) { 
int _id=sqlite3_column_int(statement, 0); 
NSString *name=(char*)sqlite3_column_text(statement, 1); 
NSLog(@"row>>id %i, name %s",_id,name); 
}
sqlite3_finalize(statement);

最后,关闭数据库:

sqlite3_close(database); 
注意:写入数据库,字符串可以采用char方式,而从数据库中取出char类型,当char类型有表示中文字符时,会出现乱码。这是因为数据库默认使用ascII编码方式。所以要想正确从数据库中取出中文,需要用NSString来接收从数据库取出的字符串。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/reylen/article/details/7977418

智能推荐

Sklearn中predict_proba函数用法及原理详解-程序员宅基地

文章浏览阅读4k次,点赞3次,收藏11次。Sklearn中predict_proba函数用法及数学原理详解(以logistic回归为例)_predict_prob

MVCC解决什么问题?原理是什么?_mvcc解决了什么问题-程序员宅基地

文章浏览阅读1.4k次。MVCC解决什么问题?原理是什么?_mvcc解决了什么问题

(邱维声)高等代数课程笔记:解线性方程组的矩阵消元法_比较消元法和初等变换求线性方程组的异同,并阐述自己的收获-程序员宅基地

文章浏览阅读383次。根据邱维声老师的高等代数课程,整理的笔记。_比较消元法和初等变换求线性方程组的异同,并阐述自己的收获

android商城首页demo,FanZhengxi-程序员宅基地

文章浏览阅读281次。Android HyBridge 开发一、三种App开发方式对比1. Native App特点:UI元素、数据内容、逻辑架构都安装在手机终端,导致不可跨平台,每次版本升级都要重新打包。缺点:无法跨平台、升级麻烦、开发成本高(指跨平台开发成本高)优点:速度快,用户体验好。2. Web App定义:可理解为移动端的网站,将网页部署在服务器上,用户通过各大浏览器来访问。缺点:页面访问速度慢、用户体验差。..._安卓应用商店app demo

好烦!快让ChatGPT停止道歉!SD创作宣传图的超细教程;教你在PH冷启动薅流量;CSDN举办AI应用创新大赛 | ShowMeAI日报_inscode deecamp x csdn ai应用创新大赛-程序员宅基地

文章浏览阅读318次。Stable Diffusion 图生图知识思维导图;使用 5W1H 框架启动一个可控的AI项目;培生集团将生成式AI学习工具引入在线高等教育平台;前 Meta AI 高管离职创业,做教育类 ChatGPT 应用……点击阅读全文_inscode deecamp x csdn ai应用创新大赛

【21天算法挑战赛】查找算法——顺序查找_普通查找是顺序查找么-程序员宅基地

文章浏览阅读814次,点赞9次,收藏7次。作者简介:我目前是一个在校学生,现在不敢说自己擅长什么,但是我想通过自己的学习努力让自己的技术、知识都慢慢提升,希望我们一起学习呀~。有话想说:写博客、记笔记并不是一种自我感动,把学到的东西记在脑子里才是最重要的,在这个过程中,不要浮躁,希望我们都可以越来越优秀!由于算法不会改变原有的元素集合,只需要一个额外的变量控制索引变化,所以空间复杂度为常数级:O(1)️兴趣领域:目前偏向于前端学习 算法学习。语言说明:代码实现我会用Python/C++~空间复杂度:O(1)

随便推点

JAVA常用实用类-程序员宅基地

文章浏览阅读1.1k次,点赞33次,收藏21次。javaAPI(java Application Programming Interface)即java应用程序编程接口,它是运行库的集合,预先定义了一些接口和类,程序员可以直接使用这些已经被打包的接口和类开发具体的应用来节约大量的时间和精力。API除了有"应用程序编程接口"的意思,还特指API的说明文档,也被称为API帮助文档。java语言的强大之处在于它提供了多种多样的类库,从而大大提高了程序的编程效率和质量,javaAPI提供常用的包如下。

常见python库学习(一)Tkinter库_GUI界面设计_python窗体类库-程序员宅基地

文章浏览阅读541次。提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、tkinter窗口1.简介2.Tkinter 控件二、1.引入库2.读入数据总结前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例可供参考一、tkinter窗口1.简介Tkinter 是使用 python 进行窗口视窗设计的模块,是 python 自带的、可_python窗体类库

通过mtd读写flash_基于STM32F7通过cube软件配置:读写QSPI接口64M flash和64M PSRAM参考教程...-程序员宅基地

文章浏览阅读825次。基于STM32F7通过cube软件配置:读写QSPI接口64M flash和64M PSRAM参考教程核心板:NUCLEO-F767ZIFlash:NM25Q64EB(64M)PSRAM:IPS6404L(64M)配置文件请使用stm32cubemx打开程序请使用keil5MDK打开NUCLEO-F767ZI上引出的QSPI引脚如下,NM25Q64EB和IPS6404L都是分别接到同样..._stm32f7 单片机 64引脚

获取栅格图层(Raster)的属性表_r raster getvalue-程序员宅基地

文章浏览阅读388次。pNewRaster是你的Raster图层IRasterBandCollection pRasterBC =(IRasterBandCollection ) pNewRaster;IRasterBand pRasterBand = pRasterBC.Item(0);ITable pTable = pRasterBand.AttributeTable;IQueryFilter pQueryFilter=new QueryFilterClass ();pQueryFilter .WhereClau._r raster getvalue

python反编译class文件_python反编译之字节码-程序员宅基地

文章浏览阅读226次。如果你曾经写过或者用过 Python,你可能已经习惯了看到 Python 源代码文件;它们的名称以.Py 结尾。你可能还见过另一种类型的文件是 .pyc 结尾的,它们就是 Python “字节码”文件。(在 Python3 的时候这个 .pyc 后缀的文件不太好找了,它在一个名为__pycache__的子目录下面。).pyc文件可以防止Python每次运行时都重新解析源代码,该文件大大节省了时间。..._python反编译class文件

hdu 2084 数塔(动态规划)-程序员宅基地

文章浏览阅读38次。本题是一个经典的动态规划题。直接利用记忆化搜索:见图解Ac code :#include<stdio.h>#include<string.h>#define max(i,j) (i>j?i:j)#define maxn 105int a[maxn][maxn];int d[maxn][maxn];int s(int i,...

推荐文章

热门文章

相关标签