ios開發常用的五種數據存儲方式:
- plist
- NSUserDefaults
- NSKeyedArchiver
- FMDB
- CoreData
這篇文章我們主要回顧NSKeyedArchiver
的使用
NSKeyedArchiver、NSKeyedUnarchiver
1.數據從內存存儲到閃存上,這個過程稱為歸檔,是將數據持久化的一種方式.
2.想要歸檔的數據對象,需要遵守NSCoding
協議,并且該對象對應的類必須提供encodeWithCoder:
和initWithCoder:
方法.
3.歸檔的缺點:歸檔的形式來保存數據,只能一次性歸檔保存以及一次性解壓,所以只能針對小量數據,而且對數據操作比較笨拙,即如果想改動數據的某一小部分,還是需要解壓整個數據或者歸檔整個數據
4.序列化與反序列化:將一個Objective-C對象轉換成NSData
的操作叫做對象的序列化
;而將一個NSData轉換成Objective-C
對象的操作叫做對象的反序列化
. 一個Objective-C對象需要通過實現NSCoding
協議以便支持序列化與反序列化.
下面我們根據之前介紹的plist以及NSUserDefault來繼續完善我們的demo(DataStorageDemo)
1.想要歸檔,就需要遵守NSCoding
協議
我們做用戶登錄的時候需要存儲用戶信息,我們給它兩個參數:用戶名與密碼
#import <Foundation/Foundation.h>
//要實現對數據模型的歸檔,需要我們實現NScoding協議,NScoping(copy協議是為了模型數據可以復制,對于歸檔而言,不是必須要實現)
@interface User : NSObject<NSCoding,NSCopying>
@property (nonatomic, strong) NSString *userName;
@property (nonatomic, strong) NSString *userPassWord;
@end
并且該對象對應的類必須提供encodeWithCoder:和initWithCoder:方法
- (void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.userName forKey:kUserName];
[aCoder encodeObject:self.userPassWord forKey:kUserPassWord];
}
- (id) initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
self.userName = [aDecoder decodeObjectForKey:kUserName];
self.userPassWord = [aDecoder decodeObjectForKey:kUserPassWord];
}
return self;
}
如果你想復制數據模型,還需要實現-(id)copyWithZone:(NSZone *)zone
-(id)copyWithZone:(NSZone *)zone
{
User *user = [[self class]allocWithZone:zone];
user.userName = [self.userName copyWithZone:zone];
user.userPassWord = [self.userPassWord copyWithZone:zone];
return user;
}
2. 存:
你可以直接存儲對象
//存儲用戶信息
User *user = [[User alloc]init];
user.userName = self.countNameTextfield.text;
user.userPassWord = self.passwordTextfield.text;
[NSKeyedArchiver archiveRootObject:user toFile:[self getFilePath]];
也可以序列化后(轉成NSData)再寫入
//存儲用戶信息
User *user = [[User alloc]init];
user.userName = self.countNameTextfield.text;
user.userPassWord = self.passwordTextfield.text;
NSMutableData *data = [[NSMutableData alloc]init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[archiver encodeObject:user forKey:@"user"];
[archiver finishEncoding];
NSLog(@"存儲路徑:%@",[self getFilePath]);
[data writeToFile:[self getFilePath] atomically:YES];
路徑:
-(NSString *)getFilePath
{
return [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0] stringByAppendingPathComponent:@"User"];
}
3. 取:
你可以直接讀取存儲的對象
if ([[NSFileManager defaultManager]fileExistsAtPath:[self getFilePath]]) {
User *user = [NSKeyedUnarchiver unarchiveObjectWithFile:[self getFilePath]];
NSLog(@"%@---%@",self.user.userName,self.user.userPassWord);
}
相應的,如果你序列化了這個對象(NSData),你就需要反序列化進行讀數
if ([[NSFileManager defaultManager]fileExistsAtPath:[self getFilePath]]) {
NSData *data = [[NSData alloc]initWithContentsOfFile:[self getFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
User *user = [unarchiver decodeObjectForKey:@"user"];
[unarchiver finishDecoding];
NSLog(@"%@---%@",user.userName,user.userPassword);
}
4. 刪
刪除很簡單
if ([defaultFileManager fileExistsAtPath:[self getFilePath]]) {
[defaultFileManager removeItemAtPath:[self getFilePath] error:nil];
}
5. NSUserDefaults存儲自定義類
之所以在這里講解這個知識點,是因為NSUserDefaults只能存儲簡單數據類型,如一個User對象,需要遵循NSCoding協議序列化成NSData之后才能使用NSUserDefaults存儲
(1). 存
User *user = [[User alloc]init];
user.userName = @"123456";
user.userPassword = @"123456";
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:user];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:data forKey:@"user"];
(2). 取
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSdData *data = [defaults objectForKey:@"user"];
User *user = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(@"%@---%@",user.userName,user.userPassword);