1. 程式人生 > >關於NSUserDefaults儲存資料的問題總結

關於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