天天看點

iOS CoraData詳解 附Xcode8系列bug

一、iOS平台下資料存儲方案

1、NSUserDefaul

//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);

2、沙盒

iOS程式預設情況下隻能通路程式自己的目錄,這個目錄被稱為“沙盒”。

雖然沙盒中有這麼多檔案夾,但是沒有檔案夾都不盡相同,都有各自的特性。是以在選擇存放目錄時,一定要認真選擇适合的目錄。      

    •    "應用程式包": 這裡面存放的是應用程式的源檔案,包括資源檔案和可執行檔案。      
  NSString *path = [[NSBundle mainBundle] bundlePath];

    •      NSLog(@"%@", path);


    •    Documents: 最常用的目錄,iTunes同步該應用時會同步此檔案夾中的内容,适合存儲重要資料。    
  NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;

    •      NSLog(@"%@", path);


    •    Library/Caches: iTunes不會同步此檔案夾,适合存儲體積大,不需要備份的非重要資料。       
  NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;

    •      NSLog(@"%@", path);


    •    Library/Preferences: iTunes同步該應用時會同步此檔案夾中的内容,通常儲存應用的設定資訊。    


    •    tmp: iTunes不會同步此檔案夾,系統可能在應用沒運作時就删除該目錄下的檔案,是以此目錄适合儲存應用中的一些臨時檔案,用完就删除。    
  NSString *path = NSTemporaryDirectory();

    •      NSLog(@"%@", path);


3、plist檔案

plist檔案是将某些特定的類,通過XML檔案的方式儲存在目錄中。   

可以被序列化的類型隻有如下幾種:

NSArray;

NSMutableArray;

NSDictionary;

NSMutableDictionary;

NSData;

NSMutableData;

NSString;

NSMutableString;

NSNumber;

NSDate;

//1.獲得檔案路徑

    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;

    NSString *fileName = [path stringByAppendingPathComponent:@"123.plist"];

//2.存儲

NSArray *array = @[@"123", @"456", @"789"];

[array writeToFile:fileName atomically:YES];

//3.讀取

NSArray *result = [NSArray arrayWithContentsOfFile:fileName];

NSLog(@"%@", result);

//4.注意

    •    隻有以上列出的類型才能使用plist檔案存儲。

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

    •    讀取時使用arrayWithContentsOfFile:方法。 


    •    新版本的iOS存的檔案目錄會生成一個上層檔案夾,檔案夾名字是随機生成的,是以絕對不要存儲本地檔案的絕對路徑,要使用相對路徑儲存


4、歸檔


歸檔在iOS中是另一種形式的序列化,隻要遵循了NSCoding協定的對象都可以通過它實作序列化。由于決大多數支援存儲資料的Foundation和Cocoa Touch類都遵循了NSCoding協定,是以,對于大多數類來說,歸檔相對而言還是比較容易實作的。    

//1.遵循NSCoding協定

NSCoding協定聲明了兩個方法,這兩個方法都是必須實作的。一個用來說明如何将對象編碼到歸檔中,另一個說明如何進行解檔來擷取一個新對象。   

    •    遵循協定和設定屬性
  //1.遵循NSCoding協定

    •      @interface Person : NSObject <NSCoding>

    •    

    •      //2.設定屬性

    •      @property (strong, nonatomic) UIImage *avatar;

    •      @property (copy, nonatomic) NSString *name;

    •      @property (assign, nonatomic) NSInteger age;

    •    

    •      @end


    •    實作協定方法    
  //解檔

    •      - (id)initWithCoder:(NSCoder *)aDecoder {

    •          if ([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"];

    •      }


    •    特别注意   
  如果需要歸檔的類是某個自定義類的子類時,就需要在歸檔和解檔之前先實作父類的歸檔和解檔方法。即 [super encodeWithCoder:aCoder] 和 [super initWithCoder:aDecoder] 方法;   


//2.使用

    •    需要把對象歸檔是調用NSKeyedArchiver的工廠方法 archiveRootObject: toFile: 方法。
  NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];

    •    

    •      Person *person = [[Person alloc] init];

    •      person.avatar = self.avatarView.image;

    •      person.name = self.nameField.text;

    •      person.age = [self.ageField.text integerValue];

    •    

    •      [NSKeyedArchiver archiveRootObject:person toFile:file];


    •    需要從檔案中解檔對象就調用NSKeyedUnarchiver的一個工廠方法 unarchiveObjectWithFile: 即可。
  NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject 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];

    •      }


//3.注意

    •    必須遵循并實作NSCoding協定    

    •    儲存檔案的擴充名可以任意指定   

    •    繼承時必須先調用父類的歸檔解檔方法      

5、資料庫 分為SQLite跟CoreData

SQLite 多使用第三方FMDB來管理 使用CocoaPods導入 添加庫即可

這裡也是要先設定資料庫檔案路徑

CoreData也可以使用第三方MagicalRecord

後面對資料庫又更進一步的了解再來操作這篇文章

一、iOS平台下資料存儲方案

1、NSUserDefaul

//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);

2、沙盒

iOS程式預設情況下隻能通路程式自己的目錄,這個目錄被稱為“沙盒”。

雖然沙盒中有這麼多檔案夾,但是沒有檔案夾都不盡相同,都有各自的特性。是以在選擇存放目錄時,一定要認真選擇适合的目錄。      

    •    "應用程式包": 這裡面存放的是應用程式的源檔案,包括資源檔案和可執行檔案。      
  NSString *path = [[NSBundle mainBundle] bundlePath];

    •      NSLog(@"%@", path);


    •    Documents: 最常用的目錄,iTunes同步該應用時會同步此檔案夾中的内容,适合存儲重要資料。    
  NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;

    •      NSLog(@"%@", path);


    •    Library/Caches: iTunes不會同步此檔案夾,适合存儲體積大,不需要備份的非重要資料。       
  NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;

    •      NSLog(@"%@", path);


    •    Library/Preferences: iTunes同步該應用時會同步此檔案夾中的内容,通常儲存應用的設定資訊。    


    •    tmp: iTunes不會同步此檔案夾,系統可能在應用沒運作時就删除該目錄下的檔案,是以此目錄适合儲存應用中的一些臨時檔案,用完就删除。    
  NSString *path = NSTemporaryDirectory();

    •      NSLog(@"%@", path);


3、plist檔案

plist檔案是将某些特定的類,通過XML檔案的方式儲存在目錄中。   

可以被序列化的類型隻有如下幾種:

NSArray;

NSMutableArray;

NSDictionary;

NSMutableDictionary;

NSData;

NSMutableData;

NSString;

NSMutableString;

NSNumber;

NSDate;

//1.獲得檔案路徑

    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;

    NSString *fileName = [path stringByAppendingPathComponent:@"123.plist"];

//2.存儲

NSArray *array = @[@"123", @"456", @"789"];

[array writeToFile:fileName atomically:YES];

//3.讀取

NSArray *result = [NSArray arrayWithContentsOfFile:fileName];

NSLog(@"%@", result);

//4.注意

    •    隻有以上列出的類型才能使用plist檔案存儲。

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

    •    讀取時使用arrayWithContentsOfFile:方法。 


    •    新版本的iOS存的檔案目錄會生成一個上層檔案夾,檔案夾名字是随機生成的,是以絕對不要存儲本地檔案的絕對路徑,要使用相對路徑儲存


4、歸檔


歸檔在iOS中是另一種形式的序列化,隻要遵循了NSCoding協定的對象都可以通過它實作序列化。由于決大多數支援存儲資料的Foundation和Cocoa Touch類都遵循了NSCoding協定,是以,對于大多數類來說,歸檔相對而言還是比較容易實作的。    

//1.遵循NSCoding協定

NSCoding協定聲明了兩個方法,這兩個方法都是必須實作的。一個用來說明如何将對象編碼到歸檔中,另一個說明如何進行解檔來擷取一個新對象。   

    •    遵循協定和設定屬性
  //1.遵循NSCoding協定

    •      @interface Person : NSObject <NSCoding>

    •    

    •      //2.設定屬性

    •      @property (strong, nonatomic) UIImage *avatar;

    •      @property (copy, nonatomic) NSString *name;

    •      @property (assign, nonatomic) NSInteger age;

    •    

    •      @end


    •    實作協定方法    
  //解檔

    •      - (id)initWithCoder:(NSCoder *)aDecoder {

    •          if ([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"];

    •      }


    •    特别注意   
  如果需要歸檔的類是某個自定義類的子類時,就需要在歸檔和解檔之前先實作父類的歸檔和解檔方法。即 [super encodeWithCoder:aCoder] 和 [super initWithCoder:aDecoder] 方法;   


//2.使用

    •    需要把對象歸檔是調用NSKeyedArchiver的工廠方法 archiveRootObject: toFile: 方法。
  NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];

    •    

    •      Person *person = [[Person alloc] init];

    •      person.avatar = self.avatarView.image;

    •      person.name = self.nameField.text;

    •      person.age = [self.ageField.text integerValue];

    •    

    •      [NSKeyedArchiver archiveRootObject:person toFile:file];


    •    需要從檔案中解檔對象就調用NSKeyedUnarchiver的一個工廠方法 unarchiveObjectWithFile: 即可。
  NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject 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];

    •      }


//3.注意

    •    必須遵循并實作NSCoding協定    

    •    儲存檔案的擴充名可以任意指定   

    •    繼承時必須先調用父類的歸檔解檔方法      

5、資料庫 分為SQLite跟CoreData

SQLite 多使用第三方FMDB來管理 使用CocoaPods導入 添加庫即可

這裡也是要先設定資料庫檔案路徑

CoreData也可以使用第三方MagicalRecord

後面對資料庫又更進一步的了解再來操作這篇文章

繼續閱讀