資料儲存的三種方式

碼鋒窩發表於2016-06-17
 
讀取info.plist檔案:
 NSDictionary *infoDict =  [NSBundle mainBundle].infoDictionary;
 NSString *version = infoDict[@"CFBundleVersion"];
一,屬性列表
屬性列表即plist檔案,實質是xml檔案。 

注意點:

    1. 根節點只能是NSArray或者NSDictionary 
    2. 如果物件是NSString、NSDictionary、NSArray、NSData、NSNumber等型別,就可以使用writeToFile:atomically:方法直接將物件寫到屬性列表檔案中
  • 將一個NSDictionary物件歸檔到一個plist屬性列表中
// 將資料封裝成字典
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"母雞" forKey:@"name"];
[dict setObject:@"15013141314" forKey:@"phone"];
[dict setObject:@"27" forKey:@"age"];
// 將字典持久化到Documents/stu.plist檔案中
[dict writeToFile:path atomically:YES];
 
 
二,偏好設定
     用於儲存APP的設定,例如是否記住密碼、是否接受推送、儲存字型大小等。
// 儲存資料
-(void)saveData
{
    // 1.獲取偏好設定
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    // 2.儲存資料
    [userDefaults setObject:@"傳智播客" forKey:@"itcastKey"];
    [userDefaults setBool:YES forKey:@"isGoodKey"];
 
/*注意:UserDefaults設定資料時,不是立即寫入,而是根據時間戳定時地把快取中的資料寫入本地磁碟。所以呼叫了set方法之後資料有可能還沒有寫入磁碟應用程式就終止了。出現以上問題,可以通過呼叫synchornize方法強制寫入
*/ 
  // 3.同步資料(iOS8)
    [userDefaults synchronize];
}

// 讀取資料
-(void)readData
{
    // 1.獲取偏好設定
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    // 2.讀取資料
    NSLog(@"%@",[userDefaults objectForKey:@"itcastKey"]);
}
 
 
三,歸檔可以將任意型別的物件,編碼後以二進位制的形式儲存。
在使用plist進行資料儲存和讀取,只適用於系統自帶的一些常用型別才能用,且必須先獲取路徑相對麻煩;
偏好設定(將所有的東西都儲存在同一個資料夾下面,且主要用於儲存應用的設定資訊)
歸檔優勢:因為前兩者都有一個致命的缺陷,只能儲存常用的型別。歸檔可以實現把自定義的物件存放在檔案中。
 
注意點:
  1. 需要歸檔的自定義類,必須實現<NSCoding>協議,告訴系統需要歸檔和解檔哪些屬性。
  2. 若物件的屬性中有自定義型別,則該類也需要實現<NSCoding>協議。
// 儲存資料
-(void)saveData
{
    // 1.建立物件
    CZPerson *person = [CZPerson new];
    person.name = @"Jack";
    person.age = 18;

    // 2.實現<NSCoding>協議

    // 3.獲取檔案路徑
    NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [documents stringByAppendingPathComponent:@"person.data"];

    // 4.編碼並儲存(歸檔)
    [NSKeyedArchiver archiveRootObject:person toFile:filePath];
}

// 讀取資料
-(void)readData
{
    // 1.獲取檔案路徑
    NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [documents stringByAppendingPathComponent:@"person.data"];

    // 2.解檔
    CZPerson *person = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

    NSLog(@"%@",person.name);
}
 
 實現<NSCoding>協議
  • encodeWithCoder什麼時候呼叫:物件歸檔時候呼叫
 
  • encodeWithCoder作用:告訴系統物件裡的哪些屬性需要歸檔,怎麼去歸檔,根據一個key去歸檔,目的就是以後取的時候,也根據這個key去取資料。
// 編碼
-(void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInteger:_age forKey:@"age"];
}
  • initWithCoder作用:告訴系統物件裡的哪些屬性需要解檔,怎麼去解檔,根據之前儲存的key去解檔
    • initWithCoder是一個初始化方法,需要先初始化父類的,但是不能呼叫[super initWithCoder:],因為父類NSObject沒有遵守NSCoding協議。
    3> initWithCoder什麼時候需要呼叫[super initWithCoder:]
    • initWithCoder原理:只要解析檔案就會呼叫,xib,storyboard都是檔案,因此只要解析這兩個檔案,就會呼叫initWithCoder。
    • 因此如果在storyboard使用自定義view,重寫initWithCoder方法,一定要呼叫[super initWithCoder:],因為只有系統才知道怎麼解析storyboard,如果沒有呼叫,就解析不了這個檔案。
// 解碼,例項化
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init])
    {//將物件的一些屬性儲存,沒有設定的屬性不作儲存
        _name = [aDecoder decodeObjectForKey:@"name"];
        _age = [aDecoder decodeIntegerForKey:@"age"];
    }
    return self;
}
 

兩個方法的區別與使用場景
/// 解歸檔 : 這個方法是把檢視從bundle載入到記憶體.檢視的frame可能不準
//- (instancetype)initWithCoder:(NSCoder *)aDecoder
//{
//    if (self = [super initWithCoder:aDecoder]) {
//        NSLog(@"%s",__func__);
//    }
//    return self;
//}

/// 檢視被喚醒的方法.在這個方法裡面可以拿到準確frame的檢視
- (void)awakeFromNib
{
 
}
 
//讀取JSON檔案,轉模型
+ (NSArray *)projects {
    // 1. 檔案路徑
    NSString *path = [[NSBundle mainBundle] pathForResource:@"more_project.json" ofType:nil];
    // 2. 讀取檔案內容 -  二進位制資料
    NSData *data = [NSData dataWithContentsOfFile:path];
    // 3. 解析JSON 專門用來解析JSON的類 NSJSONSerialization
    /**
     看到options先傳0.沒有達到效果再來看列舉值
     */
    NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    // 宣告一個可變的陣列
    NSMutableArray *projects = [NSMutableArray array];
    // 4. 遍歷資料,把字典轉成模型 - 使用block來遍歷陣列
    [json enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        CZProject *project = [CZProject projectWithDict:obj];
        [projects addObject:project];
    }];
// 將可變陣列,變成不可變 : 將執行緒不安全的類,變成了執行緒安全的類.同時,不可變的陣列,外界不能修改的.
    return projects.copy;
}
 

相關文章