天天看點

iOS應用存儲資料的常用的方式之plist和歸檔

iOS應用建立的資料存儲方式

  • plist檔案,是XML屬性的清單形式
    • ios 的偏好設定,就是基于plist檔案
  • NSKeyedArchiver

    歸檔(遵循

    NSCodeing

    協定)
  • SQLite(需要自己寫sql語句)
  • Core Data 蘋果對

    SQLite

    的一個封裝
今天我們先來說說

plist

檔案,需要知道一個概念

沙盒檔案

每一個iOS應用都有自己的沙盒檔案,與其他的檔案系統隔離,應用須待在自己的沙盒檔案裡面,其他應用不能通路該應用的沙盒檔案
  • 如何看到應用的檔案目錄呢

NSHomeDirectory()

這個方法
iOS應用存儲資料的常用的方式之plist和歸檔
從上圖中我們可以看到的目錄, 主要目錄的路徑,開頭

Application

,之前我們在

UIApplication

的時候有說過,

UIApplication

就代表一個程式的象征,是以iOS應用開頭的路徑一般都是

Application

  • 關于目錄檔案的一些介紹
  • Documents

    目錄

Documents

儲存應用

運作時生成的需要持久化的資料

,一般是

iTunes

同步裝置時來使用備份的目錄
  • tmp

    目錄

tmp

臨時存儲資料,就是當程式在次運作的時候,這些資料就會被系統删除
  • Library

    這個一般是開發人員使用的

Library

裡面存放了2個子目錄

Caches

Preferences

Caches

運作程式時生成的需要持久化資料的檔案目錄,一般下載下傳的視訊或者檔案會存儲在這個目錄,存儲的體積大

Preferences

偏好設定檔案目錄,比如:賬号 密碼 等 會與

iTunes

同步裝置時備份
  • 通路

    Documents

    目錄
/*
 第一個參數:要擷取的目錄
 第二個參數:搜尋的範圍(NSUserDomainMask:在自己檔案下搜尋)
 第三個參數:是否展開路徑
*/
  NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
           
  • 通路

    Caches

NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
           
1- 儲存資料
//擷取路徑
 NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
    
    //拼接檔案路徑 plist檔案
    NSString *filePath =[path stringByAppendingPathComponent:@"data.plist"];
    
//     NSLog(@"%@",filePath);
    NSFileManager *manager = [NSFileManager defaultManager];
    //判斷檔案或者檔案夾是否存在
    BOOL isYewOrNo = [manager fileExistsAtPath:filePath];
    if (isYewOrNo) {
       NSArray *datas = [NSArray arrayWithContentsOfFile:filePath];
        NSLog(@"%@",datas);
    }else{
        //寫入資料
        NSArray *data = @[@(110)];
        [data writeToFile:filePath atomically:YES];
        
    }
   
           
2- 儲存偏好設定的資料 這個資料就會儲存在

Preferences

目錄
//擷取檔案
   NSUserDefaults *defaluts = [NSUserDefaults standardUserDefaults];
   // 設定資料
    [defaluts setObject:@"CC" forKey:@"name_key"];
    [defaluts setObject:@"18" forKey:@"age_key"];
    //同步設定資料
    [defaluts synchronize];
           

歸檔

NSKeyedArchiver

  • 針對

    自定義的類

    進行資料存儲
  • 要進行歸檔的類,必須遵循

    NSCoding

    協定

CCPerson

類的

.h

檔案 遵循

NSCoding

@interface CCPerson : NSObject<NSCoding>

@property (nonatomic, strong) NSString *name;

@property (nonatomic, assign) int age;


@end
           

CCPerson

類的

.m

檔案 實作協定的方法
//解檔
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    
    if (self = [super init]) {
        self.name =  [aDecoder decodeObjectForKey:@"name_key"];
        self.age = [[aDecoder decodeObjectForKey:@"age_key"] intValue];
    }
    
   
    
    return self;
}


//歸檔
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.name forKey:@"name_key"];
    [aCoder encodeObject:@(self.age) forKey:@"age_key"];
    
}


           
自定義類的資料存儲
//歸檔
    
    NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
    //拼接路徑
    NSString *filepath = [path stringByAppendingPathComponent:@"person.data"];
    
     NSFileManager *manager = [NSFileManager defaultManager];
    
    if ([manager fileExistsAtPath:filepath]) {
        CCPerson *person = [NSKeyedUnarchiver unarchiveObjectWithFile:filepath];
        
        NSLog(@"%@--%d",person.name,person.age);
        
       
    }else {
        //建立對象
        CCPerson *person = [[CCPerson alloc] init];
        person.name = @"小名";
        person.age = 18;
        
        BOOL isSuc = [NSKeyedArchiver archiveRootObject:person toFile:filepath];
        NSLog(@"%@",(isSuc == YES ? @"成功":@"失敗"));
     
    }
   

           

注意:蘋果為了提高資料的安全性在

iOS11

推出了一個新的方法

+ (nullable NSData *)archivedDataWithRootObject:(id)object requiringSecureCoding:(BOOL)requiresSecureCoding error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0))
           

, 來代替下面的歸檔的方法

  • 這2個方法在

    iOS11

    之後棄用,

    iOS10

    可以使用
+ (NSData *)archivedDataWithRootObject:(id)rootObject ;

+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path ;

           
如果使用

iOS11

或者以上的系統,那麼自定義的類

CCPerson

要遵循

NSSecureCoding

協定
@interface CCPerson : NSObject<NSSecureCoding>

@property (nonatomic, strong) NSString *name;

@property (nonatomic, assign) int age;


@end
           
  • 資料存儲歸檔

    iOS11

//需要注意是:第二個參數是yes的話必須遵循NSSecureCoding,如果是NO的話可以是NSCoding協定
 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:&error];
        NSLog(@"------%@",error.description);
        
 BOOL isSuc =[data writeToFile:filepath atomically:YES];
       
  NSLog(@"%@",(isSuc == YES ? @"成功":@"失敗"));

           
儲存路徑的更改,上面再使用歸檔儲存自定義類的資料時,我們一般建立一個

來存儲路徑,友善我們使用,其實如果是

賬戶類的資料儲存

,直接存儲到

NSUserDefaults

可以
//建立對象
       CCPerson *person = [[CCPerson alloc] init];
       person.name = @"小名";
       person.age = 18;
       
       NSError *error = nil;
       
     NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:&error];
     //儲存的路徑
    NSUserDefaults *defaults  =  [NSUserDefaults standardUserDefaults];
     [defaults setObject:data forKey:@"data_key"];
      //同步資料
     defaults synchronize];