首页 > 其他 > 详细

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

时间:2015-09-09 22:59:32      阅读:493      评论:0      收藏:0      [点我收藏+]

一、数据持久化概述

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

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





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

原文:http://my.oschina.net/zooyf/blog/504095

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!