概要
四種方式:
1. NSKeyedArchiver歸檔(NSCoding)序列化
2. NSUserDefaults:用來(lái)保存應(yīng)用程序設(shè)置和屬性、用戶保存的數(shù)據(jù)。
3. NSFileManager write 的方式直接寫入磁盤
4. SQLite:采用SQLite數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)數(shù)據(jù)
一、NSKeyedArchiver歸檔(NSCoding)序列化
需要?dú)w檔解檔的類需要遵守NSCoding協(xié)議,只有遵守了NSCoding協(xié)議的類才可以用NSKeyedArchiver歸檔和NSKeyedUnarchiver解檔。
如果對(duì)象是NSString、NSDictionary、NSArray、NSData、NSNumber等類型,可以直接用NSKeyedArchiver歸檔和NSKeyedUnarchiver解檔~
缺點(diǎn):歸檔的形式來(lái)保存數(shù)據(jù),只能一次性歸檔保存以及一次性解壓。所以只能
針對(duì)小量數(shù)據(jù),而且對(duì)數(shù)據(jù)操作比較 笨拙,即如果想改動(dòng)數(shù)據(jù)的某一小部分,還
是需要解壓整個(gè)數(shù)據(jù)或者歸檔整個(gè)數(shù)據(jù)。
實(shí)現(xiàn)歸檔的四個(gè)步驟
1.遵守NSCoding協(xié)議
2.實(shí)現(xiàn)encodeWithCoder和initWithCoder方法
3.歸檔方法
4.解檔方法
1.1 遵守NSCoding協(xié)議
@interface CreateTrainOnlineCache : NSObject<NSCoding>
1.2 實(shí)現(xiàn)encodeWithCoder和initWithCoder方法
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:self.name forKey:@"name"];
[coder encodeInteger:self.age forKey:@"age"];
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
self.age = [coder decodeIntegerForKey:@"age"];
self.name = [coder decodeObjectForKey:@"name"];
}
return self;
}
1.3 歸檔
Student *s1 = [[Student alloc] init];
s1.name = @"zzz";
s1.age = 18;
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
// 這個(gè)文件后綴可以是任意的,只要不與常用文件的后綴重復(fù)即可,我喜歡用data
NSString *filePath = [path stringByAppendingPathComponent:@"student.data"];
// 歸檔
[NSKeyedArchiver archiveRootObject:s1 toFile:filePath];
1.4 解檔
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSString *filePath = [path stringByAppendingPathComponent:@"student.data"];
// 解檔
Student *s = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@----%ld", s.name, s.age);
1.5 擴(kuò)展
1.5.1 用戶數(shù)據(jù)隔離
這里筆者的應(yīng)用涉及到多用戶切換,多用戶數(shù)據(jù)之間相對(duì)隔離保密。這里筆者在用戶登錄app時(shí)便以用戶登錄名為文件名創(chuàng)立了用戶目錄,讀取都在這個(gè)個(gè)文件目錄,不同的用戶在沙盒的目錄不同,以達(dá)到用戶數(shù)據(jù)隔離的效果。
#import "NSFileManager+Paths.h"
-(NSString *)userPath{
NSString *path = [NSString stringWithFormat:@"%@/%@",[NSFileManager documentsPath],[self account]];
return path;
}
#pragma mark - 類文件本地歸檔
-(void)saveCache{
NSString *userPath = [BSEUserInfo shareMannager].userPath;
NSString *filePath = [userPath stringByAppendingPathComponent:@"onlineTrain.data"];
[NSKeyedArchiver archiveRootObject:self toFile:filePath];
}
-(void)deleteCache{
NSFileManager* fileManager = [NSFileManager defaultManager];
NSString *userPath = [BSEUserInfo shareMannager].userPath;
NSString *filePath = [userPath stringByAppendingPathComponent:@"onlineTrain.data"];
BOOL fileExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if (!fileExist) {
NSLog(@"not exist");
return ;
}else {
NSLog(@"exist");
BOOL deleteState = [fileManager removeItemAtPath:filePath error:nil];
if (deleteState) {
NSLog(@"delete success");
}else {
NSLog(@"delete fail");
}
}
}
#pragma mark - 加載本地歸檔
-(BOOL)loadCache{
NSString *userPath = [BSEUserInfo shareMannager].userPath;
NSString *filePath = [userPath stringByAppendingPathComponent:@"onlineTrain.data"];
BOOL fileExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if (!fileExist) {
NSLog(@"not exist");
return NO;
}else {
CreateTrainOnlineCache *object = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
share = object;
return YES;
}
}
1.5.2 使用runtime動(dòng)態(tài)獲取類屬性減少冗余代碼
#import <objc/runtime.h>
/**
* 根據(jù)類動(dòng)畫獲取類的所有屬性,不要忘記導(dǎo)入#import <objc/runtime.h>
*
* @param cls <#cls description#>
*
* @return <#return value description#>
*/
- (NSArray *)perperiesWithClass:(Class)cls
{
NSMutableArray *perperies = [NSMutableArray array];
unsigned int outCount;
//動(dòng)態(tài)獲取屬性
objc_property_t *properties = class_copyPropertyList(cls, &outCount);
//遍歷person類的所有屬性
for (int i = 0; i < outCount; i++)
{
objc_property_t property = properties[i];
const char *name = property_getName(property);
NSString *s = [[NSString alloc] initWithUTF8String:name];
[perperies addObject:s];
}
return perperies;
}
/**
* 歸檔會(huì)觸發(fā)
*
* @param aCoder <#aCoder description#>
*/
- (void)encodeWithCoder:(NSCoder *)aCoder
{
for (NSString *perperty in [self perperiesWithClass:[self class]])
{
[aCoder encodeObject:perperty forKey:perperty];
}
}
/**
* 解歸檔會(huì)觸發(fā)
*
* @param aDecoder <#aDecoder description#>
*
* @return <#return value description#>
*/
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init])
{
for (NSString *perperty in [self perperiesWithClass:[self class]])
{
[self setValue:[aDecoder decodeObjectForKey:perperty] forKey:perperty];;
}
}
return self;
}
二、NSUserDefaults 偏好設(shè)置
- NSUserDefaults 是一個(gè)單例對(duì)象,在整個(gè)應(yīng)用程序的生命周期中都只有一個(gè)實(shí)例。
- NSUserDefaults保存的數(shù)據(jù)類型有:
(1). 基本數(shù)據(jù)類型(int,NSInter,float,double,CGFlat......)
(2). NSNumber, NSString, NSData, NSArray, NSDictionary, NSURL。
- 其他類要是想適使用NSUserDefaults 存儲(chǔ)到本地需要 轉(zhuǎn)換成相應(yīng)的數(shù)據(jù)類型才行。如UIImage:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
UIImage *image=[[UIImage alloc]initWithContentsOfFile:@"photo.jpg"];
NSData *imageData = UIImageJPEGRepresentation(image, 100);//UIImage對(duì)象轉(zhuǎn)換成NSData
[defaults setObject: imageData forKey:@"image"];
[defaults synchronize];//立即保存
- synchronize。立即保存
蘋果文檔這么說(shuō):
Writes any modifications to the persistent domains to disk and updates all unmodified persistent domains to what is on disk.
Return Value YES if the data was saved successfully to disk, otherwise NO.
非必要函數(shù),一般寫入工作后會(huì)觸發(fā)保存。
應(yīng)用:
NSUserDefaults一般保存配置信息,比如用戶名、密碼、是否保存用戶名和密碼、是否離線下載等一些配置條件信息。
這個(gè)相信大家都用過(guò),就不細(xì)講了,直接上方法。
2.1 寫入:
//(1)基本數(shù)據(jù)類型
//保存NSInteger
[defaults setInteger:(NSInteger) forKey:(nonnull NSString *)];
//保存BOOL
[defaults setBool:(BOOL) forKey:(nonnull NSString *)];
//(2)對(duì)象
[defaults setObject:@"用戶名" forKey:kUsernameKey];
2.1 讀?。?/h3>
//(1)基本數(shù)據(jù)類型
//保存NSInteger
[defaults setInteger:(NSInteger) forKey:(nonnull NSString *)];
//保存BOOL
[defaults setBool:(BOOL) forKey:(nonnull NSString *)];
//(2)對(duì)象
NSString *username = [defaults objectForKey:kUsernameKey];
2.3 刪除
//刪除指定key的數(shù)據(jù)
[defaults removeObjectForKey:(nonnull NSString *)];
三、plist文件保存
* plist本身就是XML文件,名字后綴為.plist。
* plist主要保存的數(shù)據(jù)類型為NSString、NSNumber、NSData、NSArray、NSDictionary。
//(1)基本數(shù)據(jù)類型
//保存NSInteger
[defaults setInteger:(NSInteger) forKey:(nonnull NSString *)];
//保存BOOL
[defaults setBool:(BOOL) forKey:(nonnull NSString *)];
//(2)對(duì)象
NSString *username = [defaults objectForKey:kUsernameKey];
//刪除指定key的數(shù)據(jù)
[defaults removeObjectForKey:(nonnull NSString *)];
* plist本身就是XML文件,名字后綴為.plist。
* plist主要保存的數(shù)據(jù)類型為NSString、NSNumber、NSData、NSArray、NSDictionary。
實(shí)現(xiàn)方法:
3.1 寫入
/把字典寫入到plist文件,比如文件path為:~/Documents/data.plist
[dictionary writeToFile:path atomically:YES];
//把數(shù)組寫入到plist文件中
[array writeToFile:path atomically:YES];
3.2 讀取
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:[NSURL fileURLWithPath:(nonnull NSString *)]];
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:(nullable NSString *) ofType:(nullable NSString *)]];
四、 SQLite數(shù)據(jù)庫(kù)
這個(gè)有些非常好用的第三方庫(kù),很常見(jiàn)就不多講了直接上連接。
FMDB
這里推薦一個(gè)基于FMDB 封裝的第三方LKDBHelper,大大簡(jiǎn)化了數(shù)據(jù)庫(kù)的操作。
LKDBHelper-SQLite-ORM
數(shù)據(jù)庫(kù)將會(huì)在后面再詳細(xì)總結(jié)下,貼出常用的建表 增刪查改方法。

五、 CoreData
1 . CoreData提供了一種“對(duì)象-關(guān)系映射”的功能,能將OC對(duì)象轉(zhuǎn)化成數(shù)據(jù),保存Sqlite中。
2 . CoreData的好處就是能夠合理管理內(nèi)存,避免sql語(yǔ)句的麻煩(不用寫sql語(yǔ)句)。
CoreData構(gòu)成
- NSManagedObjectContext:被管理的數(shù)據(jù)上下文,主要作用:插入、查詢、刪除。
- NSManagedObjectModel:數(shù)據(jù)庫(kù)所有的表結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu),包含各個(gè)實(shí)體的定義的信息。主要作用就是添加實(shí)體、實(shí)體屬性,建立屬性之間的關(guān)系。
- NSPersistentStoreCoordinator持久化存儲(chǔ)助理對(duì)象,相當(dāng)于數(shù)據(jù)庫(kù)的連接器。主要作用就是設(shè)置存儲(chǔ)的名字、位置、存儲(chǔ)方式。
- NSFetchRequest相當(dāng)于select語(yǔ)句。查詢封裝對(duì)象。
- NSEntityDescription實(shí)體結(jié)構(gòu)對(duì)象,相當(dāng)于表格結(jié)構(gòu)。
- 后綴為xxx.xcdatamodeld文件,編譯后為xxx.momd的文件。
創(chuàng)建工程的時(shí)候,勾上Use Core Data。如圖所示
六、 KeyChain
- 鑰匙串(英文: KeyChain)是蘋果公司Mac OS中的密碼管理系統(tǒng)。
- 一個(gè)鑰匙串可以包含多種類型的數(shù)據(jù):密碼(包括網(wǎng)站,F(xiàn)TP服務(wù)器,SSH帳戶,網(wǎng)絡(luò)共享,無(wú)線網(wǎng)絡(luò),群組軟件,加密磁盤鏡像等),私鑰,電子證書和加密筆記等。
- iOS的KeyChain服務(wù)提供了一種安全的保存私密信息(密碼,序列號(hào),證書等)的方式。每個(gè)iOS程序都有一個(gè)獨(dú)立的KeyChain存儲(chǔ)。從iOS 3.0開(kāi)始,跨程序分享KeyChain變得可行。
- 當(dāng)應(yīng)用程序被刪除后,保存到KeyChain里面的數(shù)據(jù)不會(huì)被刪除,所以* * KeyChain是保存到沙盒范圍以外的地方。
- KeyChain的所有數(shù)據(jù)也都是以key-value的形式存儲(chǔ)的,這和NSDictionary的存儲(chǔ)方式一樣。
- 相比于NSUserDefaults來(lái)說(shuō),KeyChain保存更為安全,而且KeyChain里面保存的數(shù)據(jù)不會(huì)因?yàn)閍pp刪除而丟失