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.文件存储.界面布局.离线推送.内 ...
随机推荐
- TLS/SSL 协议 - Server Certificate
Server Certificate 典型的Certificate消息用于携带服务器X.509证书链.证书链是以ASN.1 DER编码的一系列证书,一个接着一个组合而成.主证书必须第一个发送,中间证书 ...
- 1、什么是cookie?
什么是cookie? Cookie 定义 “Cookie”是小量信息,由网络服务器发送出来以存储在网络浏览器上,从而下次这位独一无二的访客又回到该网络服务器时,可从该浏览器读回此信息.这是很有用 ...
- qemu通过命令行直接引导linux内核启动
qemu -kernel vmlinuz-3.14.0 -hda img_custom -append root=/dev/sda1
- LaTex 插入图像,以及应用表格
插入图像 参考:http://www.ctex.org/documents/latex/graphics/ 1: \includegraphics[width=20mm]{head.png} 应用表格 ...
- error C4996: 'getcwd': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _getcwd. See online help for details. c:\users\12968\desktop\testapp\testapp\testapp.c
解决办法: 属性>C/C++>预处理器定义>分别输入: _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE >保存退出即可
- Size Assert
判断返回内容的大小
- display default HeapSize of Java VM
window OS: java -XX:+PrintFlagsFinal -version | findstr HeapSize Linux OS java -XX:PrintFlagsFinal - ...
- 22-8-filter
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- JS中的垃圾回收(GC)
垃圾回收(GC): 1. 就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾,这些垃圾积攒过多以后,会导致程序运行的速度过慢, 所以我们需要一个垃圾回收的机制,来处理程序运行中产生的垃圾. ...
- tomcat之redis
Nginx服务器:[root@nginx ~]# vim /usr/local/nginx/conf/nginx.confupstream tomcat_pool { server 192.168.2 ...