UI_19 数据持久化(本地存储)

一、数据持久化概述

数据持久化就是数据的永久存储。其本质是将数据保存为文件,存到程序的沙盒中。

1、数据持久化的方式

1.1 writeToFile:简单对象写入文件

1.2 NSUserDefaults:应用程序偏好设置
1.3 Sqlite:轻量级关系型数据库,不能直接存储对象(NSData除外),需要用到一些SQL语句,先将复杂对象归档(对象->NSData)

1.4 CoreData:对象型数据库,实质是将数据库的内部存储细节封装

1.5 Plist文件

2、应用程序沙盒

每一应用程序都有自己的应用沙盒,沙盒的本质就是一个文件夹,名字是随机分配的。

与其他应用程序沙盒隔离,应用程序本身只能访问自己沙盒的数据。(iOS8+对沙盒之间的访问部分开放)

2.1 应用程序包(.app)

包含了应用程序中所用到的所有资源文件和可执行文件(Base on Unix)。iOS8时,app不存储在沙盒中,有单独的文件夹存储所有程序的app包。

2.2 HomeDirectory

Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录

tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录

Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据

Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录

2.3 获取沙盒路径

沙盒根目录NSHomeDirectory();

沙盒临时目录:NSTemporaryDirectory();


Library/Preferences:NSUserDefaults

//1.获取沙盒中Documents文件夹的路径

//第一种方式:

NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;    //NO, path = @"~/"(相对路径); YES 绝对路径

NSLog(@"%@", documentPath);

//第二种方式: (不建议采用,因为新版本的操作系统可能会修改目录名)

NSString *homePath = NSHomeDirectory();
    NSString *documentPath2 = [homePath stringByAppendingPathComponent:@"library/caches"];
    NSLog(@"%@", documentPath2);
    //2.获取应用程序包路径(.app)
    NSLog(@"%@", [NSBundle mainBundle].resourcePath);

二、简单对象持久化

1、简单对象

NSString\NSArray\NSDictionary\NSData

使用writeToFile:方法,将数据存储为.plist文件

atomically参数为是否写入缓存

//字符串

NSString *string = @"I ? U";
    //数组
    NSArray *array = @[@"张三", @"李四", @"王五"];
    //字典
    NSDictionary *dictionary = @{@"name":@"张三", @"age":@"20", @"sex":@"男"};
    //NSData
    UIImage *image = [UIImage imageNamed:@"1.jpg"];
    NSData *data = UIImageJPEGRepresentation(image, 1);
   
    //1.拼接存储路径
    NSString *strPath = [documentPath stringByAppendingPathComponent:@"string.txt"];
    NSString *arrayPath = [documentPath stringByAppendingPathComponent:@"array.txt"];
    NSString *dicPath   = [documentPath stringByAppendingPathComponent:@"dict.txt"];
    NSString *dataPath  = [documentPath stringByAppendingPathComponent:@"data.txt"];
   
    //2.写入文件
    [string writeToFile:strPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    [array      writeToFile:arrayPath   atomically:YES];
    [dictionary writeToFile:dicPath     atomically:YES];
    [data       writeToFile:dataPath    atomically:YES];
   
    //3.读取文件内容
    NSString *fileString = [NSString stringWithContentsOfFile:strPath encoding:NSUTF8StringEncoding error:nil];
    NSArray      *fileArray = [NSArray      arrayWithContentsOfFile:arrayPath];
    NSDictionary  *fileDict = [NSDictionary dictionaryWithContentsOfFile:dicPath];
    NSData            *fileData = [NSData      dataWithContentsOfFile:dataPath];
   
    NSLog(@"%@", fileString);
    NSLog(@"%@", fileArray);
    NSLog(@"%@", fileDict);

NSLog(@"%@", fileData);

2、文件管理类:NSFileManager

2.1、功能

NSFileManager使用defaultManager创建单例对象。可以创建文件夹,可以删除、移动、创建文件,判断文件是否存在。

2.2、使用

//缓存文件夹所在路径
    NSString *cachesPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
    NSLog(@"%@", cachesPath);

//在cachesPath路径下创建一个文件夹

NSString *directoryPath = [cachesPath stringByAppendingPathComponent:@"path"];
    NSFileManager *fileManager = [NSFileManager defaultManager];    //创建文件管理类单例对象
    //根据路径创建文件夹
    NSDictionary *fileDate = @{@"createTime":@"2015-9-9"};

[fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:fileDate error:nil];

//根据路径创建文件(只能写入NSData类型的数据)

[fileManager createFileAtPath:directoryPath contents:data attributes:fileDate];

//删除文件

[fileManager removeItemAtPath:dicPath error:nil];   //删除~/documents/dict.txt

3、NSUserDefaults

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];   //单例
    [defaults setValue:@"yfyfyfyfyfyfyfy" forKey:@"username"];

[defaults setValue:@"123" forKey:@"password"];

//注意:UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用synchornize方法强制写入到文件中

[defaults synchronize];

//读取

NSString *name = [defaults valueForKey:@"username"];

NSString *pwd = [defaults valueForKey:@"password"];

二、复杂对象持久化(NSKeyedArchiver)

1、复杂对象

复杂对象是在Foundation框架内不存在的数据类,无法通过writeToFile写入到文件内,且至少包含一个实例对象。

由于复杂对象无法通过writeToFile:方法写入文件,只能将复杂对象转化为NSData对象,再进行数据持久化。

2、NSCoding协议

@protocol NSCoding

- (void)encodeWithCoder:(NSCoder *)aCoder;

- (id)initWithCoder:(NSCoder *)aDecoder; // NS_DESIGNATED_INITIALIZER

@end

3、复杂对象写入文件

Person.h

//复杂对象归档 一:遵守NSCoding协议
@interface Person : NSObject<NSCoding>
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *gender;

@end

Person.m

#import "Person.h"

@implementation Person  //实现NSCoding协议

#pragma mark -- 进行编码 --
- (void)encodeWithCoder:(NSCoder *)coder
{

//    [super encodeWithCode:coder]; 如果父类也遵守了NSCoding协议,确保继承的实例变量也能被编码,即也能被归档

[coder encodeObject:self.name forKey:@"name"];

[coder encodeInteger:self.age forKey:@"age"];
    [coder encodeObject:self.gender forKey:@"gender"];

}

#pragma mark -- 进行解码 --

- (id)initWithCoder:(NSCoder *)aDecoder
{

//    self = [super initWithCoder:aDecoder]; 确保继承的实例变量也能被解码,即也能被恢复

self = [super init];

if (self) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.gender = [aDecoder decodeObjectForKey:@"gender"];
        self.age = [aDecoder decodeIntegerForKey:@"age"];
    }
    return self;

}

@end

ViewController.m

类方法进行编码\解码(只能归档一个对象):

NSString *objPath = [cachesPath stringByAppendingPathComponent:@"person.txt"];

[NSKeyedArchiver archiveRootObject:person toFile:objPath];

Person *p2 = [NSKeyedUnarchiver unarchiveObjectWithFile:objPath];

实例方法(可以归档多个对象):

#pragma mark -- 对复杂对象进行持久化(归档\编码) --

//过程:(复杂对象->归档->NSData->writeToFile:)

Person *person = [[Person alloc] init];
    person.name = @"yf";
    person.age = 20;
    person.gender = @"man";
   
    NSMutableData *mtData = [NSMutableData data];
    //创建归档器
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mtData];
    //进行归档
    [archiver encodeObject:person forKey:@"person"];
    //***结束归档
    [archiver finishEncoding];
    //将归档之后的mtData写入文件
    NSString *personPath = [cachesPath stringByAppendingPathComponent:@"person.txt"];
    [mtData writeToFile:personPath atomically:YES];
    NSLog(@"%@", personPath);

NSLog(@"%@", mtData);

#pragma mark -- 从文件中读取复杂对象(反归档\恢复\解码) --
//过程:(读取文件(NSData)->反归档->复杂对象)
    //读取
    NSData *readData = [NSData dataWithContentsOfFile:personPath];
    //创建反归档工具
    NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:readData];
    //使用反归档工具对readData进行反归档

Person *readPerson = [unArchiver decodeObjectForKey:@"person"];

4、使用NSKeyedArchive进行深复制

比如对一个Person对象进行深复制

// 临时存储person1的数据

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person1];

// 解析data,生成一个新的Person对象

Student *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];

// 分别打印内存地址

NSLog(@"person1:0x%x", person1); // person1:0x7177a60

NSLog(@"person2:0x%x", person2); // person2:0x7177cf0

时间: 2024-10-08 11:55:38

UI_19 数据持久化(本地存储)的相关文章

(尚030)Vue_案例_存储数据(localStorage本地存储技术)

当刷新页面时,会变为原来的状态 1.问题:当我刷新是不希望改变原来状态 需要缓存我当前的数据 2.究竟是缓存在内存里还是在文件里??? 缓存在文件里,因为浏览器关闭了,内存就没了;而我们需要重新打开浏览器状态还在 可以用localStorage这种本地技术(本质是缓存在文件里) 3.存储带来的问题 什么时候存?什么时候读?存啥东西进去? 界面显示是根据todos显示的,所以需要将todos存起来; 我随便做任何操作后,都是我最后的状态,也就是只要我的界面发生改变就需要存(todos改变就要存)

android:缓存服务器数据为本地存储

文章地址:http://blog.csdn.net/intbird 两个开源代码 实现想法 简单实现的一些简化做法 两个开源代码 也足够用了,没必要自己去写,文件很小 - reservoir 缓存对象为字符串; - disklrucache 存取sd卡工具; 实现想法 也就是将接口的字符串缓存到本地而已;不一定是网络缓存,可以指定任何想要的字符串保存,如果愿意可以用数据库等等,看需要咯,减轻服务器加载压力 在保证接口正常调用的情况下嵌入缓存管理方式,不对之前的代码造成任何影响,且方便替换; 不同

数据持久化,简单对象写入本地,复杂对象写入本地

#import "MainViewController.h" #import "Student.h" @interface MainViewController () @end @implementation MainViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {     self = [super initWithNi

HTML5 学习笔记(三)——本地存储

目录 一.HTML4客户端存储 1.1.提交表单发送到服务器的信息 1.2.客户端本地存储概要 二.localStorage 2.1.添加 2.2.取值 2.3.修改 2.4.删除 2.5.跨页面与跨域 2.6.存储位置与SQLite 2.7.用途.练习与兼容性 三.sessionStorage 3.1.sessionStorage使用 3.2.Web本地存储事件监听 3.3.cookie.sessionStorage.localStorage比较 四.Web SQL Database 4.1.

兼容多浏览器的本地存储

在做考试系统时需要解决这样一个问题,就是当考生考试时可能出出现断网.关闭浏览器,刷新等问题,数据此时可能没有及时写入数据库,所以造成数据丢失问题,,所以这里就需要用到本地存储,以前的版本都是用cookie,但是不得不说cookie太小了,只有可怜的4k,而机房的网有时候实在是让人捉急,所以,考虑换一种方案. 直接读取XML实现方式 因为本地存储平时接触的不是太多,开始想的只是简单的读取本地的XML,做起来倒是挺容易的,一个语句就能搞定: <script language="javascri

iOS开发——数据持久化&amp;使用NSUserDefaults来进行本地数据存储

使用NSUserDefaults来进行本地数据存储 NSUserDefaults适合存储轻量级的本地客户端数据,比如记住密码功能,要保存一个系统的用户名.密码.使用NSUserDefaults是首选.下次再登陆的时候就可以直接从NSUserDefaults里面读取上次登陆的信息. 一般来说本地存储数据我们还可以是用SQlite数据库,或者使用自己建立的plist文件什么的,但这还得自己显示创建文件,读取文件,很麻烦,而是用NSUserDefaults则不用管这些东西,就像读字符串一样,直接读取就

iOS数据持久化存储

本文中的代码托管在github上:https://github.com/WindyShade/DataSaveMethods 相对复杂的App仅靠内存的数据肯定无法满足,数据写磁盘作持久化存储是几乎每个客户端软件都需要做的.简单如"是否第一次打开"的BOOL值,大到游戏的进度和状态等数据,都需要进行本地持久化存储.这些数据的存储本质上就是写磁盘存文件,原始一点可以用iOS本身支持有NSFileManager这样的API,或者干脆C语言fwrite/fread,Cocoa Touch本身

docker mysql 数据持久化到本地、设置不区别表名大小写

Docker MySQL 把数据存储在本地目录,很简单,只需要映射本地目录到容器即可 1.加上-v参数 $ docker run -d -e MYSQL_ROOT_PASSWORD=admin --name mysql -v /data/mysql/data:/var/lib/mysql -p 3306:3306 mysql 还可以指定配置文件 docker run -d -e MYSQL_ROOT_PASSWORD=admin --name mysql -v /data/mysql/my.cn

iOS数据持久化之二——归档与设计可存储化的数据模型基类

iOS数据持久化之二--归档与设计可存储化的数据模型基类 一.引言 在上一篇博客中,我们介绍了用plist文件进行数据持久化的方法.虽然简单易用,但随着开发的深入,你会发现,这种方式还是有很大的局限性.试想,如果我们可以将用户的登录返回信息模型,游戏中角色的属性信息模型进行直接的持久化存取,那是不是非常爽的事,幸运的是,我们可以通过归档,来设计一个这样的数据模型. 二.先来精通归档吧 归档也是iOS提供给开发者的一种数据存储的方式,事实上,几乎所有的数据类型都可以通过归档来进行存取.其存储与读取