iOS开发系列-常见离线存储方式
概述
在很多社交App手机在手机没有网络时,重新启动应用,依然能否展示上次访问的数据,提高用户体验,这个就是离线数据存储的运用场景。在iOS开发中常见的离线存储技术有Plist存储、个人偏好存储、解归档、CoreData、SQLite。
Plist存储
Plist存储就是将数据写入一个指定沙盒路径的Plist文件中。如果想要更新已经写入Plist文件中的数据需要全部重新写入,因此不适合大量数据存储。并且Plist存储写入的指定类型中的数据Array、 Dictionary、 String、 Boolean、 Date 、Data 、Number。
示例:
- (void)plistCache
{
// Plist存储
// 指定写入Plist文件路径 "/Library/Caches"
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSLog(@"%@", cachePath);
// 字符串写入plist存储
NSString *str = @"123";
[str writeToFile:[cachePath stringByAppendingPathComponent:@"test.plist"] atomically:YES encoding:NSUTF8StringEncoding error:nil];
// 数组写入plist存储
[@[@"jake", @"roes"] writeToFile:[cachePath stringByAppendingPathComponent:@"array.plist"] atomically:YES];
// 字典写入plist存储
NSDictionary *dict = @{@"name":@"jake", @"age":@13, @"height": @1.98};
[dict writeToFile:[cachePath stringByAppendingPathComponent:@"dict.plist"] atomically:YES];
// NSData写入plist存储
NSData *imgData = UIImagePNGRepresentation([UIImage imageNamed:@"timg.jpeg"]);
[imgData writeToFile:[cachePath stringByAppendingPathComponent:@"data.jpeg"] atomically:YES];
}
执行代码,查看沙盒,数据被写入指定的Plist文件中。

偏好设置
偏好设置本质就是Plist存储,系统提供了一个单例NSUserDefaults,每次可以将单个类型value写入沙盒的/Library/Preference目录下的Plist文件中。该Plist命名是应用的Bundle Id。

由于个人偏好设置本质也是Plist存储,因此可以写入数据的基本数据类型只能是Array、 Dictionary、 String、 Boolean、 Date 、Data 、Number。
- (void)NSUserDefaultsCache
{
// NSUserDefaults(个人偏好存储)
[[NSUserDefaults standardUserDefaults] setObject:@"jake" forKey:@"name"];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"sex"];
[[NSUserDefaults standardUserDefaults] setDouble:1.78 forKey:@"height"];
// 立即同步
[[NSUserDefaults standardUserDefaults] synchronize];
// 移除个人偏好存储plist中的key-value
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"name"];
// 反归档从沙盒获取数据
[NSKeyedUnarchiver unarchiveObjectWithFile:@"name"];
}
在实际的开发中我们可能存储我们自定对象中的数据,这种需求上面的Plist存储和个人偏好设置存储就不能满足需求了,需要用到下面介绍的解归档存储。
解归档
解归档就是将遵守NSCoding对象的数据写入指定沙盒路径的二进制文件。如果利用解归档技术将内存中自定义对象中数据写入沙盒指定文件需要先遵守NSCoding协议。
NSCoding协议

这里我定义Person类,实现NSCoding协议,并将Person实例中的数据通过反归档写入沙盒
/***********************************Person.h*********************************************/
#import <Foundation/Foundation.h>
@interface Person : NSObject<NSCoding>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) double height;
@property (nonatomic, assign) BOOL sex;
@end
/***********************************Person.m*********************************************/
#import "Person.h"
@implementation Person
- (void)encodeWithCoder:(NSCoder *)aCoder
{
// 告诉系统哪些属性需要归档
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeDouble:self.height forKey:@"height"];
[aCoder encodeInt:self.age forKey:@"age"];
[aCoder encodeBool:self.sex forKey:@"sex"];
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.height = [aDecoder decodeDoubleForKey:@"height"];
self.age = [aDecoder decodeIntForKey:@"age"];
self.sex = [aDecoder decodeBoolForKey:@"sex"];
}
return self;
}
- (NSString *)description
{
NSString *string = [NSString stringWithFormat: @"name=%@, height=%f, age=%d, sex=%d", self.name, self.height, self.age, self.sex];
return string;
}
解归档Person示例
- (void)archiverCache
{
// 获取路径
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
// 归档
// 对于开发中自定义的数据模型的储存,我们可以考虑使用归档储存方案。
Person *p = [[Person alloc] init];
p.name = @"jake";
p.height = 1.78;
p.age = 18;
p.sex = YES;
[NSKeyedArchiver archiveRootObject:p toFile:[cachePath stringByAppendingPathComponent:@"pData"]];
// 返归档从沙盒中取出Person示例对象
id person = [NSKeyedUnarchiver unarchiveObjectWithFile:[cachePath stringByAppendingPathComponent:@"pData"]];
NSLog(@"%@", person);
}
CoreData
CoreData 是一个纯粹面向对象的框架,可以管理实体以及实体之间的关联关系的持久化,也就是我们常说的数据持久化。
但是由于它是一个重量级的数据库管理,产生很多代码量。对于复杂的联合表查询不适用 并且出错不容易解决或找到问题,需要有很深的开发功底。
目前开发一般使用嵌入式数据库SQLite替代。这里就不详细介绍了。
SQLite
SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。
SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于250KiB。
SQLite 可在 UNIX(Linux, Mac OS-X, Android, iOS)和 Windows(Win32, WinCE, WinRT)中运
SQLite数据类型
| SQLite数据类型 | 对应OC类型 |
|---|---|
| INTEGER | 整型 |
| TEXT | 文本 |
| REAL | 浮点型 |
| BLOB | 二进制数据 |
注意:SQLite这里没有对应OC中的BOOL类型。
SQLite语句
对于SQLite的语句已基本与MySQLite一直,可以参考我的博客MySQL。
这里有两点需要注意下,设置主键自动增长使用AUTOINCREMENT,不要使用MySQL的auto_increment带下划线的样式。

SQLite在应用
对于iOS程序使用SQLite苹果提供了静态库

sqlite3提供的接口纯C语言,开发起来比较费劲,一般我们使用GitHub的对其封装的第三方库FMDB。
对于FMDB的使用可以参考我简书上的博客FMDB使用。
iOS开发系列-常见离线存储方式的更多相关文章
- 怎样实现IOS开发中的数据存储方式
iOS 开发中,一般有如下几种数据存储方式.需要根据具体的业务场景,选择 合适的数据存储方式. (1) 用户默认设置 – 这种情况通常不需要用户干预,如游戏通关信息,Video 播放记录,或者 Ap ...
- 【Xamarin 挖墙脚系列:IOS 开发界面的3种方式】
原文:[Xamarin 挖墙脚系列:IOS 开发界面的3种方式] xcode6进行三种基本的界面布局的方法,分别是手写UI,xib和storyboard.手写UI是最早进行UI界面布局的方法,优点是灵 ...
- iOS开发系列--App扩展开发
概述 从iOS 8 开始Apple引入了扩展(Extension)用于增强系统应用服务和应用之间的交互.它的出现让自定义键盘.系统分享集成等这些依靠系统服务的开发变成了可能.WWDC 2016上众多更 ...
- iOS开发系列--Swift进阶
概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ...
- iOS开发系列--让你的应用“动”起来
--iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...
- iOS开发系列--让你的应用“动”起来
--iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...
- IOS开发系列 --- 核心动画
原始地址:http://www.cnblogs.com/kenshincui/p/3972100.html 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...
- iOS开发系列--让你的应用“动”起来【转载】
概览 原文链接:http://www.cnblogs.com/kenshincui/p/3972100.html 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...
- iOS开发系列之app的一天
本文主要讲述我对 iOS 开发的一些理解,希望能通过 app 从启动到退出,将一些的知识整合起来,形成一条知识链,目前涉及到的知识点有 runloop.runtime.文件存储.界面布局.离线推送.内 ...
随机推荐
- Nginx学习——proxy_pass
参考官网:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass 定义:用来设置被代理服务器的协议(http或https ...
- [已解决]报错UnicodeDecodeError
输出报错: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc4 in position 220: in 解决方案:将编码方式utf-8 修 ...
- python输入一个\输出2个\问题
在Python里面,如果\后面不是一个合法的转移字符,那么,Python会打印两个\,换句话说,Python将\也当成普通字符看待,而不是转义符的标志: >>>S = 'C:\py\ ...
- Couleur(启发式 + 主席树)(终于补坑了)
ZOJ Problem Set - 4053 Couleur Time Limit: 6 Seconds Memory Limit: 131072 KB DreamGrid has an a ...
- android项目各个文件详解
res目录说明 android应用的res目录是一个特殊的目录,该项目里存放了 android应用所用的全部资源,包括图片资源.字符串资源. 颜色资源.尺寸资源等. /res/value/string ...
- Windows跳板机无法共享本地主机剪贴板
我的跳板机是Windows 2003 ,总是无法共享本地的剪贴板,我一般是在本地编辑SQL或者一些脚本,然后粘贴到跳板机中. 如果碰到无法共享本地剪贴板的情况,可以尝试按照以下步骤解决: 开始 -- ...
- axios的介绍及使用
特点:支持promise API . 拦截请求和响应.转换请求数据和响应数据.取消请求.自动转换JSON数据.客户端支持防御XSRF等: axios请求方法(需后端定义):get获取数据. post提 ...
- 制作一个自己的xhprof测试平台
1 1.首先安装php开发环境,比如lnmp. 2.安装xhprof ps: 记住从github上面下载(https://github.com/phacility/xhprof), 不要从pecl.p ...
- wget 下载文件
# -c 继续执行上次终端的任务# --http-user http用户名# --http-passwd http密码# --no-check-certificate 不检查ssl/tsl证书. wg ...
- TFS中的账号和GIT中的账号
有些公司使用TFS来进行git的管理,这个时候很多人没有区分TFS中的账号和GIT的账号的区别:TFS的账号和GIT账号是两套不同的体系,使用TFS管理GIT GIT是不需要账号密码,但是必须在win ...