1.为什么要进行数据持久化?
我们平时的浏览记录,qq的聊天记录,收藏夹等,每次打开程序的视乎都会存在,理论上每次关闭应用的时候,程序中使用的数据资源都应该被释放,将程序运行过程中或运行结束后的某些信息持久的保存起来就是数据持久化。
2:什么是数据持久化
将数据模型转换成存储模型(内存中某些对象保存到磁盘中)
3:数据持久化的优点
就是将数据持久话的保存起来,不会丢失
4.数据持久化的方式:
①:文件
② plist文件:属性列表文件,相当于一个小型数据库,持久话一些比较小的数据,xml格式,持久话数组和字典对象
③归档和反归档:将内存中的对象保存在磁盘中
④NSUserDefaults: 持久化标签(UI)
⑤数据库:
sqlite
FMDB:对sqlite封装
coredata: 数据库的基础上封装了一层面向对象的第三方库
**
PList
**
1:什么是plist文件
plist全称:property List 属性列表文件,plist是一个xml格式文件,后缀为.plist,只能持久化NSArray和NADictionary类型对象
2:plist文件的作用
作用:plist是做数据持久化的专业文件,.plist一般情况下用于存储用户密码、临时信息、简介这样的简单的信息
3:Plist文件特点(先将Xcode创建plist文件,通过创建好的plist文件介绍plist文件特点)
a:plist文件的根路径(root)是数组或字典类型(plist文件只能持久化数组或字典对象)
b:plist文件的自路径只能是NSString NSNumber NSDate NSData NSArray NSDictionary类型的对象
4:Xcode创建plist文件
Plist文件内容的格式是xml语法格式
创建步骤
①.点击File–》New File 弹出一对话框
②.iOS程序选中iOS栏中的Resource/Mac程序选中OS X 栏中的resource
③.点击Resource中的Property List 创建plist文件
④.点击文件中的’+’可以添加数据
5:代码创建和读取plist文件
如果想把NSString NSNumber NSDate NSData NSArray NSDictionary类的对象写入文件中一般用plist文件,但是因为plist文件根路径只能是NSArray和NSDoctionary所以只能持久化NSArray和NSDoctionary对象,这时候就需要将数据保存在数组或字典中然后调用数组和字典的相关方法把数组和字典写入到plist文件中
//将数组和字典写入plist文件的方法
//path:plist文件的路径
//useAuxiliaryFile:是否具有原子性
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
//将plist文件读取到数组和字典中
//将plist文件读取到数组中(类方法)
+(id)arrayWithContentsOfFile:(NSString *)path;
//将plist文件读取到字典中(类方法)
+(id)dictionaryWithContentsOfFile:(NSString *)path
例:
/*
//将数组写入到plist文件中
例子1:创建一个数组,数组成员是NSString类型的对象@“ni”,@“hao”,@“ma”
把该数组持久化到一个plist文件中,并读取plist文件中内容
*/
void arrayToPList1(void){
NSString *pathDesktop = @"/Users/mac/Desktop";
NSArray *array = [NSArray arrayWithObjects:@"bei", @"ni", @"hao", @"ma", nil];
//- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
//将数组写入到plist文件
[array writeToFile:[pathDesktop stringByAppendingString:@"/arrayPlist1.plist"] atomically:YES];
//+ (id /* NSArray * */)arrayWithContentsOfFile:(NSString *)path;
//作用:将plist文件中的数据读到数组中
NSArray *arrayFromPList = [NSArray arrayWithContentsOfFile:[pathDesktop stringByAppendingString:@"/arrayPlist1.plist"]];
NSLog(@"%@", arrayFromPList);
**
归档和反归档
**
1:什么是归档和反归档
归档:归档就是通过某种格式把内存中的某个对象保存到本地文件中,以便以后再从该文件中读回该对象
反归档:把归档的对象文件读成原来的内存中的对象
2.如何归档和反归档
//归档
+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path;
//反归档
+ (id)unarchiveObjectWithFile:(NSString *)path;
a. 系统类的归档和反归档
例:
//array的归档和反归档
void stringArchiverAndUnarchiver(void){
NSString *pathDesktop = @"/Users/mac/Desktop";//桌面路径
NSArray *array = @[@"nihao",@"iOS"];
//+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path;
//作用:系统类对象进行归档
BOOL success = [NSKeyedArchiver archiveRootObject:array toFile:[pathDesktop stringByAppendingString:@"/string归档文件"]];
if (success){
NSLog(@"归档成功");
}else{
NSLog(@"归档失败");
}
//+ (id)unarchiveObjectWithFile:(NSString *)path;
//作用:归档文件的反归档
NSString *stringFromFile = [NSKeyedUnarchiver unarchiveObjectWithFile:[pathDesktop stringByAppendingString:@"/string归档文件"]];
NSLog(@"%@", stringFromFile);
注:对于系统类NSString和NSArray和NSDictionary对象都可以直接进行归档和反归档操作
b.自定义类的归档和反归档
对于系统类NSString和NSArray和NSDictionary对象可以直接进行归档和反归档操作,是不是说所有的类的对象都能进行归档和反归档
只有遵守了协议的类的对象才能进行归档和反归档操作
如果自定义的类对象要进行归档那么这个对象的属性所属的类也必须要遵守归档协议NSCoding
必须实现以下两个方法:
//归档的时候调用的方法
- (void)encodeWithCoder:(NSCoder *)aCoder;
//解归档的时候要调用的函数
- (id)initWithCoder:(NSCoder *)aDecoder;
例子:创建一个Student类,类中有_age和_name两个实例变量,堆Student类对象进行归档和反归档操作
Student类
Student.h
//对于一个自定义的类想要进行归档和反归档操作必须遵守NSCoding协议
//遵守NSCoding协议
#import <Foundation/Foundation.h>
//.h文件类的声明后面加上<协议名>,表示该类遵守这个协议
@interface Student : NSObject <NSCoding>
@property (assign, nonatomic)int age;
@property (copy, nonatomic)NSString *name;
//协议中的内容
- (void)encodeWithCoder:(NSCoder *)aCoder;//归档操作的时候自动被调用
- (id)initWithCoder:(NSCoder *)aDecoder;//反归档的时候自动被调用
@en
Student.m
//.m实现协议中的方法
#import "Student.h"
@implementation Student
//归档的时候调用
- (void)encodeWithCoder:(NSCoder *)aCoder{
//- (void)encodeInt:(int)intv forKey:(NSString *)key;
//作用:归档int类型的数据
//key:归档的格式,归档格式任意但是以什么格式归档就需要以什么格式反归档
[aCoder encodeInt:self.age forKey:@"age"];
//- (void)encodeObject:(id)objv forKey:(NSString *)key;
//作用:归档oc对象
[aCoder encodeObject:self.name forKey:@"name"];
}
- (id)initWithCoder:(NSCoder *)aDecoder{
//- (int)decodeIntForKey:(NSString *)key;
//作用:反归档int类型数据
if(self = [super init]){
self.age = [aDecoder decodeIntForKey:@"age"];
self.name = [aDecoder decodeObjectForKey:@"name"];
}
return self;
}
viewController.m
NSString *pathDesktop = @"/Users/mac/Desktop";
Student *std = [[Student alloc] init];
std.age = 10;
std.name = @"xiao xin";
[NSKeyedArchiver archiveRootObject:std toFile:[pathDesktop stringByAppendingString:@"/归档文件student"]];
Student *stdFromArchiver = [NSKeyedUnarchiver unarchiveObjectWithFile:[pathDesktop stringByAppendingString:@"/归档文件student"]];
NSLog(@"age is %d name is %@", stdFromArchiver.age, stdFromArchiver.name);
}
**
Json
**
(1) 什么是JSON
JSON是一种轻量级的数据交换格式, JSON语法是 JavaScript 语法的子集;
JSON 数据的书写格式是: 名称:值 构成键值对。(类似于OC字典的键值对)
(2) JSON的基本语法
名称/值对 包括字段名称(在双引号中), 后面写一个冒号,然后是值。如 “firstName”:”tom”
JSON的值可以是:
a. 数字 (整数或浮点数)
b. 字符串 (在双引号中)
c. 逻辑值 (true 或 false)
d. 数组 (在方括号中)
e. 对象 (在花括号中)
f. null
(3) JSON结构
JSON有数组和字典两种结构 ; 通过这两种结构可以表示各种复杂的结构;
1:数组:数组在json中是中括号‘[]’括起来的内容,数据结构为[“java”,”javascript”,”vb”,…],类似于OC中的数组
2:对象:对象在json中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,…}的键值对的结构,类似于oc中的字典结构
json的结构也决定了json最终只能转换成数组或字典类型的对象
@{key : value}
(4)json文件解析(analysis)
本地json解析步骤:
1:首先调用NSString的
+ (id)stringWithContentsOfFile:(NSString )path encoding:(NSStringEncoding)enc error:(NSError *)error;
方法将文件读成字符串
2:然后调用NSString的
- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding;
把字符串转换成NSData二进制数据
3:调用系统类NSJSONSerialization的
+ (id)JSONObjectWithData:(NSData )data options:(NSJSONReadingOptions)opt error:(NSError *)error;
方法进行解析,最后解析为NSArray或者NSDictionary
例子:对本地jsonUserList.txt文件进行解析
//json文件的解析
void JsonAnalysis1(void){
NSString *pathDesktop = @"/Users/mac/Desktop";
//1:读取json文件内容保存在string
NSString *string = [NSString stringWithContentsOfFile:[pathDesktop stringByAppendingString:@"/json/jsonUserList.txt"] encoding:NSUTF8StringEncoding error:nil];
//2:把string转换成data
NSData *dataFromString = [string dataUsingEncoding:NSUTF8StringEncoding];
//3:将data进行json解析
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:dataFromString options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@", dictionary);
}
NSUserDefaults
(1)NSUserDefaults是一个单例,在整个程序中只有一个实例对象,他可以用于数据的永久保存,而且简单实用,适合存储轻量级的本地数据,比如要保存一个登陆界面的数据,用户名、密码之类的,使用NSUserDefaults就比较简单了。
(2)NSUserDefaults支持的数据格式有:NSNumber(Integer、Float、Double),NSString,NSDate,NSArray,NSDictionary,BOOL类型。
(3)例子
//将NSString 对象存储到 NSUserDefaults 中
NSString *string = @"小明";
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
[user string forKey:@"name"];
将数据取出,代码如下:
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
NSString *string = [ user objectForKey:@"name"];
注意:对相同的Key赋值约等于一次覆盖,要保证每一个Key的唯一性
注意:
NSUserDefaults 存储的对象全是不可变的(这一点非常关键,弄错的话程序会出bug),例如,如果我想要存储一个 NSMutableArray 对象,我必须先创建一个不可变数组(NSArray)再将它存入NSUserDefaults中去,代码如下:
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"123",@"234", nil];
NSArray * array = [NSArray arrayWithArray:mutableArray];
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
[user setObject:array forKey:@"记住存放的一定是不可变的"];
取出数据是一样的,想要用NSUserDefaults中的数据给可变数组赋值
先给出一个错误的写法:
/*-------------------------错误的赋值方法-------------------*/
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
//这样写后,mutableArray 就变成了不可变数组了,如果你要在数组中添加或删除数据就会出现bug
NSMutableArray *mutableArray = [user objectForKey:@"记住存放的一定是不可变的"];
正确的写法:
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
//可以用alloc 方法代替
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:[user objectForKey:@"记住存放的一定是不可变的"]];
(4)使用 NSUserDefaults 存储自定义对象
如果存储的数据量比较大,一般选择用SQLite、FMDB或者CoreData来存储。SQLite、FMDB或者CoreData的介绍放在下一篇章节。