iOS常用的几种数据存储方式
之前由于刚入行不久,对数据持久化不是很了解,尤其是用数据库存储大量数据的操作。经过摸索就在此总结一下,方便以后查阅
下面就简单介绍一下:
1.NSUserDefaults
感觉最常用的小量数据,属性,例如,账号,密码之类的;适合存储轻量级的本地数据 (个人认为这种比较简单)
NSUserDefaults支持的数据格式有:NSNumber(Integer、Float、Double),NSString,NSDate,NSArray,NSDictionary,BOOL类型
直接看代码比较容易理解:
// 测试数据
NSArray *myArray = [NSArray arrayWithObjects:@"hello", @"world", nil];
NSDictionary *myDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"enuo", @"", nil] forKeys:[NSArray arrayWithObjects:@"name", @"age", nil]];
// 存入
[[NSUserDefaults standardUserDefaults] setObject:myArray forKey:@"arry"];
[[NSUserDefaults standardUserDefaults] setObject:myDictionary forKey:@"dict"]; //这里建议同步存储到磁盘中,但是不是必须的
[[NSUserDefaults standardUserDefaults] synchronize]; // 读取
NSArray *arr= [[NSUserDefaults standardUserDefaults] objectForKey:@"arry"];
NSDictionary *dict = [[NSUserDefaults standardUserDefaults] objectForKey:@"dict"];
NSLog(@"------%@----\n-----%@------",arr,dict); // 清除数据
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"keyName"];
建议:[NSUserDefaults standardUserDefaults] 可以在项目中定义一个全局的宏,这样使用起来更便捷。
2.归档
目的是为了长时间存放有组织的数据集
(1)简单的归档方式 但是只能存储单个对象。
// (1)归档
NSArray *array = [NSArray arrayWithObjects:@,@,@, nil];
NSString *filePath = [NSHomeDirectory() stringByAppendingString:@"testFile.plist"];
BOOL success = [NSKeyedArchiver archiveRootObject:array toFile:filePath]; NSLog(@"%d",success);
NSLog(@"%@",filePath); // (2)反归档
NSString *filePath = [NSHomeDirectory() stringByAppendingString:@"testFile.plist"];
id OUTarray = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@",OUTarray);
(2)可以将多个对象归档成一个文件。
// (1)归档
NSMutableArray *arrayArchiver = [NSMutableArray arrayWithObjects:@"BigDragon",@"BigBiao",@"BigBaby", nil];
NSMutableData *data = [NSMutableData data]; NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//编码
[archiver encodeObject:arrayArchiver forKey:@"array"];
[archiver encodeObject:@"Jason‘s friends" forKey:@"name"]; //编码完成之后,对象已经存储到data之中。
[archiver finishEncoding]; NSString *filePathtwo = [NSHomeDirectory() stringByAppendingPathComponent:@"arraytwo.plist"];
BOOL successtwo = [data writeToFile:filePathtwo atomically:YES];
NSLog(@"------%d",successtwo); // (2)反归档 NSString *filePathtwo = [NSHomeDirectory() stringByAppendingPathComponent:@"arraytwo.plist"];
//读取归档数据
NSData *dataUnarchiver = [[NSData alloc] initWithContentsOfFile:filePathtwo]; //创建解归档对象,进行反归档
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:dataUnarchiver]; //反归档
NSArray *arrayUnarchiver = [unarchiver decodeObjectForKey:@"array"];
NSLog(@"----%@",arrayUnarchiver); NSString *nameUnarchiver = [unarchiver decodeObjectForKey:@"name"];
NSLog(@"-----%@",nameUnarchiver);
(3)使用工具类(感觉如果使用归档,一般使用工具类,相对来说便捷一点)
下面就先建个工具类;Person类
Person.h
#import <Foundation/Foundation.h> @interface Person : NSObject<NSCoding> //需要遵守NSCoding协议 @property (nonatomic,strong) NSString *name; //带归档类型
@property (nonatomic,assign) NSInteger age;
@property (nonatomic,strong) NSString *gender; - (NSString *)description;
@end
Person.m
/**
该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码
*/ // 归档方法
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
[aCoder encodeObject:self.gender forKey:@"gender"];
}
// 反归档方法
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init]; if (self != nil) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
self.gender = [aDecoder decodeObjectForKey:@"gender"];
}
return self;
} - (NSString *)description
{
NSString *string = [NSString stringWithFormat:@"%@\n %ld\n %@",self.name,self.age,self.gender];
return string;
}
在控制器用的时候:
Person *person = [[Person alloc]init]; person.name = @"rose";
person.age = ;
person.gender = @"man"; // 归档,调用归档方法
NSString *filePath3 = [NSHomeDirectory() stringByAppendingString:@"person.plist"];
BOOL success3 = [NSKeyedArchiver archiveRootObject:person toFile:filePath3];
NSLog(@"=====%d",success3); // 反归档,调用反归档方法
Person *per = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath3];
NSLog(@"=======%@",per);
3.写入文件
主要的步骤:
//第一步:获得文件即将保存的路径:(永久保存在磁盘中)
// 文件存储的相对目录
NSArray *filePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString*path = filePaths.firstObject; //第二步:生成在该路径下的文件:
NSString *FileName=[path stringByAppendingPathComponent:@"flieName"];//fileName就是保存文件的文件名
// 第三步:往文件中写入数据:
NSData *data;
[data writeToFile:FileName atomically:YES];//将NSData类型对象data写入文件,文件名为FileName
// 最后:从文件中读出数据:
NSData *outdata=[NSData dataWithContentsOfFile:FileName options: error:NULL];//从FileName中读取出数据
下面就简单的举几个例子
#pragma mark--1.字符串写入
// NSString *strfilepath = [path stringByAppendingPathComponent:@"str.text"];
NSString *strfilepath = [path stringByAppendingString:@"/text.text"];
NSString *INstr = @"字符串写入文件";
[INstr writeToFile:strfilepath atomically:YES encoding:NSUTF8StringEncoding error:nil]; // 读取文件
NSString *OUTstr = [[NSString alloc]initWithContentsOfFile:strfilepath encoding:NSUTF8StringEncoding error:nil];
NSLog(@"----%@-----",OUTstr); #pragma mark-2、数组对象写入文件
// 构造数组plist文件的存储路径
NSString*arrypath = [path stringByAppendingPathComponent:@"arry.plist"];
NSArray *INarr = @[@"hahah",@"hehhe",@"heihei"];
[INarr writeToFile:arrypath atomically:YES]; // 读取文件
NSArray *outarr = [[NSArray array]initWithContentsOfFile:arrypath];
NSLog(@"----%@-----",outarr); #pragma mark-3、字典对象写入文件
NSString*dictpath = [path stringByAppendingPathComponent:@"dict.plist"];
NSDictionary *dict = @{@"姓名":@"liuwenqiang",@"年龄":@"",@"职业":@"ios"};
[dict writeToFile:dictpath atomically:YES]; // 读取文件
NSDictionary *OUTdict = [[NSDictionary alloc]initWithContentsOfFile:dictpath];
NSLog(@"----%@-----",OUTdict); #pragma mark-4、二进制对象写入文件
NSString *datapath = [path stringByAppendingPathComponent:@"song.m4a"];
UIImage *image = [UIImage imageNamed:@"image"];
NSData *imagedata = UIImageJPEGRepresentation(image, );
[imagedata writeToFile:datapath atomically:YES]; // 读取文件
NSData *OUTdata = [[NSData alloc]initWithContentsOfFile:datapath];
NSLog(@"----%@-----",OUTdata);
4.数据库
对于大型的数据存储,再使用上面的方法显然不适用了,该使用数据库了,我在项目中使用的是第三方的数据库FMDB,个人感觉比较好用,使用比较顺手。
那么什么是大型数据,我认为的就是那种像app里的列表之类的,由于列表的数据量相当比较大,如果像我们的应用,列表中还有列表图的话,那就更大了。
当初在看数据库之前,总感觉很难理解,不好学,但是慢慢的理解了,也并不是那么难理解,(下面的方法是需要在工具类的.h中声明的,这样控制器中才能调到)
在操作之前,需要先下载一个FMDB 拉到项目中 附上: FMDB下载地址
先创建一个工具类 fmbdTool
(1)创库建表
@implementation FmdbTool {
FMDatabase *db;
}
-(NSString*)createFMDBTable:(NSString *)type
{
NSString *str;
//1.获得数据库文件的路径
NSString *doctorpath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *filePath = [doctorpath stringByAppendingPathComponent:@"doctor.sqlite"];
// NSLog(@"-------路径----%@-------",filePath);
//2.获得数据库
db = [FMDatabase databaseWithPath:filePath];
//3.打开数据库
if ([db open]) {
//4.创表
BOOL result;
if ([type isEqualToString:@"doctor"]) { result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_doctor (id integer PRIMARY KEY AUTOINCREMENT,doctordict blob NOT NULL,page_ID integer NOT NULL,datacount text NOT NULL)"]; } if (result) {
// NSLog(@"====建表成功--------type=== %@",type); str = @"yes"; }else
{
NSLog(@"====建表失败");
str = @"no";
}
}else {
NSLog(@"faile to create a FMDB");
str = @"no";
} return str;
}
在我的项目中,由于有很多的列表要做数据存储,因此我在创建库的方法中加了一个参数type,为每个要存储的页面都建一张表,并把所有的表都放到
doctor.sqlite这个库中。
在创建表的时候,首先要[db open]打开数据库,该返回数据类型是bool,当为真的时候,再创建表
result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_doctor (id integer PRIMARY KEY AUTOINCREMENT,doctordict blob NOT NULL,page_ID integer NOT NULL,datacount text NOT NULL)"];
doctordict是个数字类型的数据,就是像后台返回的下面数据中,doctorInfoList字段,所以doctordict的类型是blob 。并且由于该字段不可能为空,故在建表的时候 NOT NULL 。
列表做了分页请求,所以在表中把页码存储了,page_ID integer NOT NULL。 datacount是列表总的页数。
(2)插入数据
//插数据
-(void)addDataInsetTable:(NSArray *)doctorListArry page:(NSInteger)page datacount:(NSString*)datacount type:(NSString *)type
{
if ([db open]) { NSString *pagestr = [NSString stringWithFormat:@"%ld",(long)page];
NSError *err = nil; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:doctorListArry options:NSJSONWritingPrettyPrinted error:&err]; NSString *jsonStr = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding]; if ([type isEqualToString:@"doctor"]) { [db executeUpdate:@"INSERT INTO t_doctor (doctordict,page_ID,datacount) VALUES (?,?,?);",jsonStr,pagestr,datacount]; } }
[db open]; }
插入数据是也是 先[db open]之后才能插入数据。
通过这个方法可以看出,我直接就可以把后台返回给我的数据,responseObject[@"doctorInfoList"] 插到表中,
在插入之前,需要先把数组转成json类型的字符串,我在这里使用了,JSONKit JSONKit下载地址
(3).取数据
-(NSArray *)outdata:(NSString *)type
{
NSArray *dataArr; NSMutableArray *aaarr = [[NSMutableArray alloc]init];
if ([db open]) { if ([type isEqualToString:@"doctor"]) {
FMResultSet *res = [db executeQuery:@"SELECT * FROM t_doctor"]; while (res.next) { NSString *s = [res stringForColumn:@"doctordict"]; NSArray *aa = [s objectFromJSONString]; [aaarr addObjectsFromArray:aa];
dataArr = aaarr; } }
} [db close]; return dataArr;
}
//取出当前页数 在该type时
-(NSString *)checkoutpage:(NSString *)type
{
NSString *str;
if ([db open]) { FMResultSet *res = [db executeQuery:@"SELECT * FROM t_activesecond where type = ?",type]; while (res.next)
{
str = [res stringForColumn:@"page"];
}
}
[db close]; return str;
}
(4).删除数据
//删除数据
- (void)deleteData:(NSString *)type
{ if ([db open]) { if ([type isEqualToString:@"doctor"]) {
NSString *deleteSql = [NSString stringWithFormat:@"delete from t_doctor"];
[db executeUpdate:deleteSql]; }
} [db close];
}
我在删除数据的时候,只删除了,指定表,并没有直接把库删了,因为所以的表都在这个库里。
先写到这吧,如果哪里说错了,请指出,谢谢啦。
iOS常用的几种数据存储方式的更多相关文章
- IOS开发数据存储篇—IOS中的几种数据存储方式
IOS开发数据存储篇—IOS中的几种数据存储方式 发表于2016/4/5 21:02:09 421人阅读 分类: 数据存储 在项目开发当中,我们经常会对一些数据进行本地缓存处理.离线缓存的数据一般都 ...
- Android中常用的五种数据存储方式
第一种: 使用SharedPreferences存储数据 适用范围: 保存少量的数据,且这些数据的格式非常简单:字符串型.基本类型的值.比如应用程序的各种配置信息(如是否打开音效.是否使用震动效果.小 ...
- Android编程中的5种数据存储方式
Android编程中的5种数据存储方式 作者:牛奶.不加糖 字体:[增加 减小] 类型:转载 时间:2015-12-03我要评论 这篇文章主要介绍了Android编程中的5种数据存储方式,结合实例形式 ...
- Android五种数据存储方式
android 五种数据存储 :SharePreferences.SQLite.Contert Provider.File.网络存储 Android系统提供了四种存储数据方式.分别为:SharePre ...
- IOS的四种数据存储方式及优劣
IOS有四种经常使用数据存储方式: 第一种方法:用NSUserDefaults存储配置信息 NSUserDefaults被设计用来存储设备和应用的配置信息.它通过一个工厂方法返回默认的.也是最经常使用 ...
- Android中的5种数据存储方式
本文转自 http://hi.baidu.com/maguowei/blog/item/7aca46c25574a33ae5dd3ba4.htmlAndroid数据存储Android提供了5种方式存 ...
- Android四种数据存储方式
一.SharedPreference数据存储篇 1.作用范围 (1).它是一种轻型的数据存储方式 (2).本质是基于XML文件存储key-value键值对数据 (3).通常用来存储一些简单的配置方式 ...
- [ Android 五种数据存储方式之四 ] —— ContentProvider存储数据
Android这个系统和其他的操作系统还不太一样,我们需要记住的是,数据在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据.那这个时候有读者就会提出问题,难道两个 ...
- [ Android 五种数据存储方式之一 ] —— SharedPreferences存储数据
SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数. 主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceS ...
随机推荐
- Tomcat抛出异常:ClientAbortException: java.net.SocketException: Connection
在做一个小网站的时候,写了一个通过servlet实现文件下载功能的页面.当我点击超级练级,弹出下载对话框,点击保存正常下载,不会出现任何问题,当我我点击取消,服务器端就出现如下提示: ClientAb ...
- Navicat for MySQL Mac 破解版
今天在macOS 系统下搭建 Java开发环境,需要配置MySQL,按照Windows的习惯,使用Navicat for MySQL 操作比较习惯.然后找不到比较好的破解版,这里介绍一个老版的,还是英 ...
- WinStore控件之Button、HyperlinkButton、RadioButton、CheckBox、progressBar、ScrollViewer、Slider
1.Button protected override void OnNavigatedTo(NavigationEventArgs e) { /* * Button - 按钮控件,其全部功能是通过其 ...
- [LeetCode] Sparse Matrix Multiplication
Problem Description: Given two sparse matrices A and B, return the result of AB. You may assume that ...
- Visual Studio快捷键 [VS2008/VS2005]快捷键
VS系统通用快捷键: 1.自动排版(类似VC6中的Alt+F8) 编辑.格式化选定内容 Ctrl + K,Ctrl + F 根据周围的代码行,正确缩进选定的代码行. 2.注释与去掉注释功能. 编辑.注 ...
- 公钥、私钥、CA认证、数字签名、U盾
感谢传智播客的方立勋老师,在一个教学视频上,他巧妙地以蒋介石给宋美龄写密信作为例子,生动地讲述了软件密码学知识. 加密分为对称加密和非对称加密,我们传统理解的,发送数据之前使用一个加密器加密,接到数据 ...
- SSAS:菜鸟笔记(二)定义计算(DMX脚本)
基本概念 Calculation可以定义计算成员.名称集以及执行其他脚本命令来扩展分析服务立方(Analysis Service Cube)的功能. Calculation包含MDX以及脚本两个部分: ...
- linq join多字段
from VS in m2db.Inf_VehicleSale join RS1 in m2db.His_RecSale on new { VS.vehicleCode, auctionCode=VS ...
- Chart 点击获取坐标
private void chart2_MouseMove(object sender, MouseEventArgs e) { if (!this.DesignMode) { ].AxisX.Sca ...
- Redis配置以及通过C#访问小试
首先安装一个Ubuntu14.04的虚拟机用来安装Redis.Ubuntu的Unity在虚拟机里面卡爆了,可以通过如下方法安装传统的Gnome界面: sudo aptitude install gno ...