iOS學習筆記15 序列化、偏好設定和歸檔

執著丶執念發表於2018-06-02

###一、本地持久化 所謂的持久化,就是將資料儲存到硬碟中,使得在應用程式或機器重啟後可以繼續訪問之前儲存的資料。在iOS開發中,有很多資料持久化的方案,接下來我將嘗試著介紹一下5種方案:

  1. plist檔案(序列化)
  1. preference(偏好設定)
  2. NSKeyedArchiver(歸檔)
  3. SQLite3
  4. CoreData

本節我就只寫關於歸檔、偏好設定和屬性列表的,這些都是小資料持久化常用的方式,SQLite3和CoreData都是資料庫大資料儲存的方式,以後再寫。

###二、沙盒 在介紹各種儲存方法之前,有必要說明以下沙盒機制。iOS程式預設情況下只能訪問程式自己的目錄,這個目錄被稱為“沙盒”。

既然沙盒就是一個資料夾,那就看看裡面有什麼吧。沙盒的目錄結構如下:

  • 應用程式包:存放的是應用程式的原始檔,包括資原始檔和可執行檔案
NSString *path = [[NSBundle mainBundle] bundlePath];
複製程式碼
  • Documents:最常用的目錄,iTunes同步該應用時會同步此資料夾中的內容,適合儲存重要資料
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject;
複製程式碼
  • Library
  • Caches:iTunes不會同步此資料夾,適合儲存體積大,不需要備份的非重要資料。
NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES).firstObject;
複製程式碼
  • Preferences:iTunes同步該應用時會同步此資料夾中的內容,通常儲存應用的設定資訊。
  • tmp: iTunes不會同步此資料夾,系統可能在應用沒執行時就刪除該目錄下的檔案,所以此目錄適合儲存應用中的一些臨時檔案,用完就刪除。
NSString *path = NSTemporaryDirectory();
複製程式碼

###三、plist檔案(序列化) plist檔案是將某些特定的類,通過XML檔案的方式儲存在目錄中。 ######可以被序列化的型別只有如下幾種:

NSArray;//陣列
NSMutableArray;//可變陣列
NSDictionary;//字典
NSMutableDictionary;//可變字典
NSData;//二進位制資料
NSMutableData;//可變二進位制資料
NSString;//字串
NSMutableString;//可變字串
NSNumber;//基本資料
NSDate;//日期
複製程式碼

######以NSArray為例,其他類使用方法完全相似:

- (void)writeToPlist{
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject;
    NSString *fileName = [path stringByAppendingPathComponent:@"123.plist"];
    NSArray *array = @[@"1234", @"tony", @"java"];
    //序列化,把陣列存入plist檔案
    [array writeToFile:fileName atomically:YES];
}
- (NSArray *)readFromPlist{
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject;
    NSString *fileName = [path stringByAppendingPathComponent:@"123.plist"];
    //反序列化,把plist檔案資料讀取出來,轉為陣列
    NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
    NSLog(@"%@", result);
    return result;
}
複製程式碼

儲存時使用writeToFile:atomically:方法。 其中atomically表示是否需要先寫入一個輔助檔案,再把輔助檔案拷貝到目標檔案地址。這是更安全的寫入檔案方法,一般都寫YES

plist檔案圖示

###四、Preference(偏好設定) 偏好設定是專門用來儲存應用程式的配置資訊的,一般不要在偏好設定中儲存其他資料。 偏好設定是以key-value的方式進行儲存和讀寫,使用到一個單例物件NSUserDefaults ######下面是使用方法:

//1.獲得NSUserDefaults檔案
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
//2.向偏好設定中寫入內容
[userDefaults setObject:@"AAA" forKey:@"a"];
[userDefaults setBool:YES forKey:@"sex"];
[userDefaults setInteger:21 forKey:@"age"];
//2.1立即同步
[userDefaults synchronize];
//3.讀取偏好設定
NSString *name = [userDefaults objectForKey:@"a"];
BOOL sex = [userDefaults boolForKey:@"sex"];
NSInteger age = [userDefaults integerForKey:@"age"];
NSLog(@"%@, %d, %ld", name, sex, age);
複製程式碼
  • 如果沒有呼叫synchronize方法,系統會根據I/O情況不定時刻地儲存到檔案中。所以如果需要立即寫入檔案的就必須呼叫synchronize方法。
  • 偏好設定會將所有資料儲存到同一個檔案中,使用同一個key進行儲存資料,會覆蓋之前儲存的資料。

###五、歸檔和解檔 歸檔在iOS中是另一種形式的序列化,只要遵循了NSCoding協議的物件都可以通過它實現序列化。由於絕大多數支援儲存資料的類都遵循了NSCoding協議,因此,對於大多數類來說,歸檔相對而言還是比較容易實現的。 ####1. 遵循NSCoding協議 ######NSCoding協議宣告瞭兩個方法,這兩個方法都是必須實現的:

encodeWithCoder:用來說明如何將物件編碼到歸檔中。 initWithCoder:用來說明如何進行解檔來獲取一個新物件。

//1.遵循NSCoding協議 
@interface Person : NSObject <NSCoding> 
//2.設定屬性
@property (strong, nonatomic) UIImage *avatar;
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) NSInteger age;
@end

@implementation Person 
//解檔
- (id)initWithCoder:(NSCoder *)aDecoder {
      if (self = [super init]) {
          self.avatar = [aDecoder decodeObjectForKey:@"avatar"];
          self.name = [aDecoder decodeObjectForKey:@"name"];
          self.age = [aDecoder decodeIntegerForKey:@"age"];
      }
      return self;
}
//歸檔
- (void)encodeWithCoder:(NSCoder *)aCoder {
      [aCoder encodeObject:self.avatar forKey:@"avatar"];
      [aCoder encodeObject:self.name forKey:@"name"];
      [aCoder encodeInteger:self.age forKey:@"age"];
}
@end
複製程式碼

####2. NSKeyedArchiver歸檔 呼叫NSKeyedArchiverarchiveRootObject:toFile:方法把物件歸檔

NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject; 
NSString *file = [path stringByAppendingPathComponent:@"person.data"];
Person *person = [[Person alloc] init];
person.avatar = [UIImage imageNamed:@"icon.png"];
person.name = @"Xiao Ming";
person.age = 17;
[NSKeyedArchiver archiveRootObject:person toFile:file];
複製程式碼

####3. NSKeyedUnarchiver解檔 呼叫NSKeyedUnarchiverunarchiveObjectWithFile:方法從檔案中解檔物件

NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject; 
NSString *file = [path stringByAppendingPathComponent:@"person.data"];
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
if (person) {
    self.avatarView.image = person.avatar;
    self.nameField.text = person.name;
    self.ageField.text = [NSString stringWithFormat:@"%ld", person.age];
}
複製程式碼
  • 必須遵循並實現NSCoding協議
  • 儲存檔案的副檔名可以任意指定
  • 繼承時必須先呼叫父類的歸檔解檔方法,這裡因為父類是NSObject,就不用了

以上就是小資料持久化的3種常用方法,下一節我將繼續寫大資料持久化的常用方法,敬請期待!!下面來個美女,沒配圖強迫症發作!

動漫美女助興,來配圖

######如果喜歡,請點關注,如果不喜歡,請點喜歡,O(∩_∩)O哈!

相關文章