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.文件存储.界面布局.离线推送.内 ...
随机推荐
- 3.1 开始使用 redux
前面我们介绍了 flux 架构以及其开源实现 redux,在这一节中,我们将完整的介绍 redux: redux 介绍 redux 是什么 redux 概念 redux 三原则 redux Store ...
- POJ 3130 How I Mathematician Wonder What You Are! (半平面交)
题目链接:POJ 3130 Problem Description After counting so many stars in the sky in his childhood, Isaac, n ...
- (转载)前端构建工具gulpjs的使用介绍及技巧
本文转载自:https://www.cnblogs.com/2050/p/4198792.html gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API ...
- Django框架(十一)—— 常用字段、参数、元信息、多对多关联关系
目录 常用字段和参数 一.ORM字段 二.ORM参数 三.关系字段 1.ForeignKey 2.OneToOneFiled 3.ManyToManyField 四.元信息 五.多对多关联关系的三种方 ...
- 20140806 交换两个数 extern “C”用法
1.交换两个数 方法1.a+b有可能越界 a=a+b; b=a-b; a=a-b; 方法二.不会越界 a=a^b b=a^b; a=a^b; 2.extern "C"用法 ( ...
- nginx配置跨域
location / { if ($request_method = 'OPTIONS') {add_header 'Access-Control-Allow-Origin' '*' always;a ...
- PXE装机
支持 centOS 6 支持 PXE 装机的网卡必须自带 ROM(非意识性存储器)存储内容包括:DHCP 客户端,TFTP 客户端,PXE 协议客户端,将网卡设置第一启动项. DHCP:自动分配 IP ...
- html5本地存储(三)--- 本地数据库 indexedDB
html5内置了2种本地数据库,一是被称为“SQLLite”,可以通过SQL语言来访问文件型SQL数据库.二是被称为“indexedDB” 的NoSQL类型的数据库,本篇主要讲indexedDB数据库 ...
- Thymeleaf语法总结
Thymeleaf是Spring boot推荐使用的模板引擎. 一.th属性 html有的属性,Thymeleaf基本都有,而常用的属性大概有七八个.其中th属性执行的优先级从1~8,数字越低优先级越 ...
- Servlet - Tomcat服务器相关
1. 服务器 : 服务器其实就是代码编写的一个程序, 可以根据用户发送的请求, 调用执行对应的逻辑代码 2. Tomcat目录结构说明 : \bin : 存放启动和关闭Tomcat的可执行文件 \co ...