關於NSUserDefaults儲存資料的問題總結
大家都知道,NSUserDefaults適合儲存輕量級的本地資料,並且在不刪除程式的情況下是永久儲存的。
NSUserDefaults支援的資料格式有:NSNumber(Integer、Float、Double),NSString,NSDate,NSArray,NSDictionary,BOOL型別。
這裡說明一下,這裡只說了NSString,NSArray,NSDictionary等,其對應的NSMutableString,NSMutableArray,NSMutableDictionary也是可以的,因為後者分別都是前者的子類。
NSUserDefaults只能直接或者是間接(間接指巢狀)的儲存它支援的資料型別,其他的型別都是不可以的。
但是有的時候我們想儲存自定義的模型,直接儲存會崩潰,需要做一些額外的處理就可以了。下面是NSUserDefaults儲存自定義模型的方法:
這是自定義的模型ChatLogModel類
點h 需要新增NSCoding協議
#import <Foundation/Foundation.h> @interface ChatLogModel : NSObject<NSCoding> @property(nonatomic,copy)NSString *name; @property(nonatomic,assign)BOOL isVideo; @property(nonatomic,strong)NSString *date; @end
點m 實現NSCoding協議中的兩個方法
使用的時候#import "ChatLogModel.h" #define NAME @"name" #define ISVIDEO @"isVideo" #define DATE @"date" @implementation ChatLogModel - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.name forKey:NAME]; [aCoder encodeBool:self.isVideo forKey:ISVIDEO]; [aCoder encodeObject:self.date forKey:DATE]; } - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { if (self = [super init]) { self.name = [aDecoder decodeObjectForKey:NAME]; self.isVideo = [aDecoder decodeBoolForKey:ISVIDEO]; self.date = [aDecoder decodeObjectForKey:DATE]; } return self; } @end
-(void)storeChatLog
{
// 取
NSData *data1 = [[NSUserDefaults standardUserDefaults] objectForKey:@"chatlog"];
NSMutableArray *chatLogArray = [NSKeyedUnarchiver unarchiveObjectWithData:data1];
if ((chatLogArray.count == 0)) {
chatLogArray = [NSMutableArray arrayWithCapacity:1];
}
ChatLogModel *chatmodel = [[ChatLogModel alloc] init];
chatmodel.name = @"張三";
chatmodel.isVideo = YES;
// 獲取當前時間
NSDate *currentDate = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MM-dd hh:mm:ss"];
NSString *dateString = [formatter stringFromDate:currentDate];
chatmodel.date = dateString;
[chatLogArray addObject:chatmodel];
// 存
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:chatLogArray];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"chatlog"];
[[NSUserDefaults standardUserDefaults] synchronize];
// 取
NSData *data2 = [[NSUserDefaults standardUserDefaults] objectForKey:@"chatlog"];
NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:data2];
NSLog(@"array:%@",array);
}
儲存到NSUserDefaults的時候是先把陣列歸檔成NSData,然後儲存在NSUserDefaults中
從NSUserDefaults取出的時候是用NSData取出,再把NSData解檔成陣列
我這裡是使用了陣列,陣列也可以替換成字典或者其他。如果想直接儲存自定義模型,省略陣列,則可以這樣:
// 存
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:model];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"chatlog"];
[[NSUserDefaults standardUserDefaults] synchronize];
// 取
NSData *data1 = [[NSUserDefaults standardUserDefaults] valueForKey:@"chatlog"];
ChatLogModel *chatmodel = [NSKeyedUnarchiver unarchiveObjectWithData:data1];
只是存取有區別,其他的相同。
注意:是NSCoding協議,不是NSCopying協議。本人之前就混淆了
以下是NSCoding協議和NSCopying協議對應的方法,用以區分:
@protocol NSCopying
- (id)copyWithZone:(nullableNSZone *)zone;
@end
@protocol NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (nullableinstancetype)initWithCoder:(NSCoder *)aDecoder; // NS_DESIGNATED_INITIALIZER
@end