數據存儲(一)

數據持久化的本質其實就是:將數據寫入文件保存起來。

關于沙盒

出于安全方面的考慮,iOS系統的沙盒機制規定每個應用程序都只能訪問當前沙盒目錄下的文件,而不能訪問其他的應用程序的沙盒的內容,對該應用程序內容起到保護作用。
每個應用的沙盒有以下4個目錄:

  • Documents: 用來存儲長久保存的數據
  • xxx.app: 應用程序的包, 包含應用程序加載所需的所有資源(readonly只讀, 不可修改), 平時使用的NSBundle就是該包
  • Library:
    1. Caches: 本地緩存, 存儲想暫時保存的數據
    2. Preferences: 存儲用戶的偏好設置, 比如程序是否是第一次啟動
  • tmp: 保存各種的臨時文件

獲取上述各個目錄,首先得獲取根目錄
NSString *homePath = NSHomeDirectory();

獲取Documents

//獲取Documents文件夾目錄,第一個參數是說明獲取Documents文件夾目錄,第二個參數說明是在當前應用沙盒中獲取
NSArray *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES); 
NSString *documentsPath = [docPath objectAtIndex:0];  

獲取Cache目錄

NSArray *cacPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);  
NSString *cachePath = [cacPath objectAtIndex:0];

獲取temp目錄
NSString *tempPath = NSTemporaryDirectory();

對象歸檔

歸檔可以實現把對象存放在文件中,只要遵循了NSCoding協議的對象都可以通過它實現序列化。要實現NSCoding協議,需要下列兩個方法:

  • -(void)encodeWithCoder:(NSCoder *)aCoder;
  • -(instancetype)initWithCoder:(NSCoder *)aDecoder;

而對于對象是NSString,NSDictionary,NSArray,NSData,NSNumber等類型,可以直接使用NSKeyedArchiver進行歸檔和解檔。

  NSString *path = NSHomeDirectory();
  NSString *archiverPath = [path stringByAppendingPathComponent:@"ftt.archiver"];
  NSArray *array = @[@"abc",@"feg",@"opq"];
  BOOL flag = [NSKeyedArchiver archiveRootObject:array toFile: archiverPath];
    if (flag) {
        NSLog(@"歸檔成功");
    }
// 解檔(讀取)
  NSArray *Arr = [NSKeyedUnarchiver unarchiveObjectWithFile:archiverPath];
  NSLog(@"%@",Arr);

接下來實現想將一個自定義的對象保存到文件中,新建一個類FTPerson。

//.h文件中
#import <Foundation/Foundation.h>
// 如果想將一個自定義的對象保存到文件中必須實現NSCoding協議
@interface FTPerson : NSObject <NSCoding>
// 姓名
@property (nonatomic, copy)NSString *name;
// 年齡
@property (nonatomic,assign) NSInteger age;
// 身高
@property (nonatomic, assign) double height;

// 實現NSCoding協議中的兩個方法
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (instancetype)initWithCoder:(NSCoder *)aDecoder;
@end

接著在FTPerson.m文件中實現NSCoding協議中的兩個方法

#import "FTPerson.h"
@implementation FTPerson
// 當將一個自定義的對象保存到文件的時候就會調用該方法
- (void)encodeWithCoder:(NSCoder *)aCoder {
    NSLog(@"調用了encodeWithCoder: 方法");    
    [aCoder encodeObject:self.name forKey:@"name"];      
    [aCoder encodeInteger:self.age forKey:@"age"];
    [aCoder encodeDouble:self.height forKey:@"height"];   
}

// 當從文件中讀取一個對象的時候就會調用該方法
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    NSLog(@"調用了initWithCoder:方法");    
    // 注意:在構造方法中需要先初始化父類的方法    
    if (self = [super init]) {        
        self.name = [aDecoder decodeObjectForKey:@"name"];       
        self.age = [aDecoder decodeIntegerForKey:@"age"];        
        self.height = [aDecoder decodeDoubleForKey:@"height"];    
    }
    return self;
}
@end

在viewController.m文件中導入FTPerson.h

- (void)saveData {
    FTPerson *p = [[FTPerson alloc] init];
    p.name = @"Tom";
    p.age = 22;
    p.height = 1.8;
    // 獲取文件路徑
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)firstObject];
    NSString *path = [docPath stringByAppendingPathComponent:@"person.fountain"];
    NSLog(@"path = %@",path);
    // 歸檔
    [NSKeyedArchiver archiveRootObject:p toFile:path];                        
}

- (void)readData {
    // 獲取文件路徑
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)firstObject];
    NSString *path = [docPath stringByAppendingPathComponent:@"person.fountain"];
    //解檔
    FTPerson *p = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    NSLog(@"name = %@,age = %lu,height = %lf",p.name,p.age,p.height);
    
}

如果需要實現一個子類FTStudent,繼承自FTPerson,增加一個屬性weight。那么子類FTStudent一定要重寫
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (instancetype)initWithCoder:(NSCoder *)aDecoder;
這兩個方法,因為FTPerson的子類在存取的時候,會去子類中去找調用的方法,沒找到那么它就去父類中找,所以最后保存和讀取的時候新增加的屬性就會被忽略。需要先調用父類的方法,即在encodewithCoder:方法中先加上一句[super encodeWithCoder:aCoder];在initWithCoder:方法中加上一句self = [super initWithCoder:aDecoder];先初始化父類的,再初始化子類的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一、iOS應用數據存儲的常用方式: 1> XML屬性列表(plist)歸檔2> Preference(偏好設置)3...
    DB001閱讀 1,521評論 0 5
  • 一、應用沙盒 一般情況下,iOS每個應用程序都只能訪問當前沙盒目錄下的文件。 (一)、沙盒目錄 Documents...
    f1e583c455bf閱讀 390評論 0 0
  • 前言:在我們開發過程中,不管是你做啥子應用,都要遇到數據的保存問題。將數據保存本地,這樣讓程序的運行更加流暢,不在...
    480a52903ce5閱讀 16,824評論 13 16
  • 下面是我最近兩年學習OC中的一些基礎知識,對于學習OC基礎知識的人可能有些幫助,拿出來分享一下,還是那句話不喜勿噴...
    小小趙紙農閱讀 2,657評論 1 7
  • 概論 所謂的持久化,就是將數據保存到硬盤中,使得在應用程序或機器重啟后可以繼續訪問之前保存的數據。在iOS開發中,...
    Leeson1989閱讀 1,969評論 4 1