iOS的數(shù)據(jù)存儲

背景

在iOS開發(fā)中必不可少的要用到數(shù)據(jù)存儲,數(shù)據(jù)的處理是iOS開發(fā)中的核心技術(shù),適當?shù)膶?shù)據(jù)進行持久化存儲可以實現(xiàn)應(yīng)用的離線功能,以此提高用戶體驗。所謂數(shù)據(jù)持久化,就是將數(shù)據(jù)保存到硬盤中,使得在應(yīng)用程序或手機重啟后可以繼續(xù)訪問之前保存的數(shù)據(jù)。在iOS開發(fā)中,有很多持久化得方案,接下來我將總結(jié)以下5種持久化方案:
1、plist(屬性列表)
2、preference(偏好設(shè)置)
3、NSKeyedArchiver(歸檔)
4、SQList 3 (FMDB)
5、CoreData

應(yīng)用沙盒

在介紹各種存儲方法之前,先說明下沙盒機制。每個iOS應(yīng)用都有一個 應(yīng)用沙盒「文件系統(tǒng)目錄」,與其他文件系統(tǒng)隔離
應(yīng)用必須在自己的沙盒里,其他應(yīng)用不能訪問他人的沙盒

EAA11FC5-13D8-41A6-AF51-83FFE21E3808.png
  • Documents:保存應(yīng)用運行時生成的需要持久化的數(shù)據(jù),iTunes同步設(shè)備時會備份該目錄。例如,游戲應(yīng)用可將游戲存檔保存在該目錄

  • tmp:保存應(yīng)用運行時所需的臨時數(shù)據(jù),使用完畢后再將相應(yīng)的文件從該目錄刪除。應(yīng)用沒有運行時,系統(tǒng)也可能會清除該目錄下的文件。iTunes同步設(shè)備時不會備份該目錄

  • Library/Caches:保存應(yīng)用運行時生成的需要持久化的數(shù)據(jù),iTunes同步設(shè)備時不會備份該目錄。一般存儲體積大、不需要備份的非重要數(shù)據(jù)

  • Library/Preference:保存應(yīng)用的所有偏好設(shè)置,iOS的Settings(設(shè)置)應(yīng)用會在該目錄中查找應(yīng)用的設(shè)置信息。iTunes同步設(shè)備時會備份該目錄


    // 獲取 Documents 文件路徑
    // 方法一、利用沙盒根目錄拼接 ”Documents” 字符串
    // 不建議采用,因為新版本的操作系統(tǒng)可能會修改目錄名
    NSString *home = NSHomeDirectory();
    NSString *documents = [home stringByAppendingPathComponent:@"Documents"];

// 方法二、利用 NSSearchPathForDirectoriesInDomains 函數(shù)
    
    /**
     NSSearchPathForDirectoriesInDomains

     @param NSDocumentDirectory 搜索目錄是,Documents 目錄
     @param NSUserDomainMask 搜索范圍是,用戶文件夾
     @param NO 不展開全路徑:~/Library/Caches
     @return NSArray*
     */
    
    NSArray *documentArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath = [documentArray firstObject];
    NSLog(@"documentPath = %@",documentPath);
    
    
    NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)firstObject];
    NSLog(@"libraryPath = %@",libraryPath);
    
    NSString *preferencePath =[libraryPath stringByAppendingString:@"/preferences"];
    NSLog(@"%@",preferencePath);
    
    
    NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)firstObject];
    NSLog(@"cachesPath = %@",cachesPath);

    // 獲取 tmp 文件路徑
    NSString *tmpPath = NSTemporaryDirectory();


plist(屬性列表)

iOS提供了一種plist格式的文件(屬性列表)用于存儲輕量級的數(shù)據(jù),屬性列表是一種XML格式的文件,拓展名為plist。如果對象是NSString、NSDictionary、NSArray、NSData類型,就可以使用writeToFile:atomically:?法 直接將對象寫到屬性列表文件中該格式保存的數(shù)據(jù)可以直接使用NSDictionary和NSArray讀取 。plist文件在iOS開發(fā)中屬于Write寫入方式,可以以Property List列表形式顯示,也可以以xml格式顯示。對于數(shù)據(jù)管理是很方便的。掌握使用plist文件數(shù)據(jù)操作很有必要.

  • NSString 寫入文件 讀取
 NSArray *documentArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath = [documentArray firstObject];
    NSLog(@"documentPath = %@",documentPath);
    
    NSString *filePath = [documentPath stringByAppendingPathComponent:@"str.txt"];
    NSString *str = @"這是一個字符串";
    //atomically是否進行線性操作(YES保證發(fā)生意外時有中轉(zhuǎn)文件來保存信息 直至寫入完成 但是損耗大. NO的時候?qū)懭胨俣瓤?但是沒有安全保障)
    [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    
    NSString *str1 = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    //2017-03-19 15:28:09.740 信號量[3255:166796] 這是一個字符串
    NSLog(@"%@",str1);

D2A41CA4-9724-414A-9CA1-8808E22778E5.png
  • NSArray 寫入文件 讀取
  NSArray *documentArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath = [documentArray firstObject];
    NSLog(@"documentPath = %@",documentPath);
    
    NSString *filePath = [documentPath stringByAppendingPathComponent:@"arr.txt"];
    NSArray *array = @[@"abc",@"def",@"ghi"];
    [array writeToFile:filePath atomically:YES];
    
    NSArray *getArray = [NSArray arrayWithContentsOfFile:filePath];
//    2017-03-19 15:34:52.261 信號量[3423:172597] (
//                                              abc,
//                                              def,
//                                              ghi
//                                              )
    NSLog(@"%@",getArray);

81CF3301-99E0-4F30-97B8-8FABADE86B14.png
  • NSDictionary 寫入文件 讀取
  NSArray *documentArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath = [documentArray firstObject];
    NSLog(@"documentPath = %@",documentPath);
    
    NSString *filePath = [documentPath stringByAppendingPathComponent:@"arr.txt"];
    NSDictionary *dic = @{@"name":@"jack",@"age":@"13"};
    [dic writeToFile:filePath atomically:YES];
    
    NSDictionary *mydic = [NSDictionary dictionaryWithContentsOfFile:filePath];
//    2017-03-19 15:39:03.598 信號量[3479:176290] {
//        age = 13;
//        name = jack;
//    }

    NSLog(@"%@",mydic);
    
2838F4E0-9011-432E-B103-5B45FFD5545B.png
  • NSData對象寫入 讀取
 NSArray *documentArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath = [documentArray firstObject];
    NSLog(@"documentPath = %@",documentPath);
    
    NSString *filePath = [documentPath stringByAppendingPathComponent:@"22.png"];
   
    UIImage *image = [UIImage imageNamed:@"22.png"];
    
    NSData *data = UIImagePNGRepresentation(image);
    
    [data writeToFile:filePath atomically:YES];
    
    NSData *myData = [NSData dataWithContentsOfFile:filePath];
    //2017-03-19 15:45:55.005 信號量[3666:183586] 3157
    NSLog(@"%lu",(unsigned long)myData.length);

75B9FBD2-6013-47E3-B489-C4D877CE79C0.png

preference(偏好設(shè)置)

使用NSUserDefault 實現(xiàn)持久化
下面來看下 NSUserDefault 本地保存的位置,Library/Preferences 這個目錄下的 plist 文件就是其保存的目錄。

  //1.獲得NSUserDefaults文件
  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
  //2.向文件中寫入內(nèi)容
  [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"];

881054C8-D179-4E02-AAF0-4AF35E1AB9EF.png

偏好設(shè)置是專門用來保存應(yīng)用程序的配置信息的,一般不要在偏好設(shè)置中保存其他數(shù)據(jù)。
如果沒有調(diào)用synchronize方法,系統(tǒng)會根據(jù)I/O情況不定時刻地保存到文件中。所以如果需要立即寫入文件的就必須調(diào)用synchronize方法。
偏好設(shè)置會將所有數(shù)據(jù)保存到同一個文件中。即preference目錄下的一個以此應(yīng)用包名來命名的plist文件。

NSKeyedArchiver(歸檔)

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;

@end
#import "Person.h"
//遵守NSCoding協(xié)議
@interface Person()<NSCoding>


@end

@implementation Person

#pragma mark 編碼,對象屬性進行編碼
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    //前者(_age,_name)是屬性,后者是關(guān)鍵字Key(age,name)
    [aCoder encodeInt:_age forKey:@"age"];
    [aCoder encodeObject:_name forKey:@"name"];
}

#pragma mark 解碼,解碼歸檔數(shù)據(jù)初始化對象
- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {
        _age = [aDecoder decodeIntForKey:@"age"];
        _name = [aDecoder decodeObjectForKey:@"name"];
    }
    return self;
}

@end

測試

  NSArray *documentArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath = [documentArray firstObject];
    NSLog(@"documentPath = %@",documentPath);
    
    NSString *filePath = [documentPath stringByAppendingPathComponent:@"person"];
    
    
    Person *p = [Person new];
    p.name =@"wang";
    p.age = 12;
    //Encoding保存Person
    [NSKeyedArchiver archiveRootObject:p toFile:filePath];
    
    Person *pp = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
//    2017-03-19 16:32:16.750 信號量[4359:217706] wang
//    2017-03-19 16:32:16.751 信號量[4359:217706] 12
    NSLog(@"%@",pp.name);
    NSLog(@"%d",pp.age);

SQList 3和CoreData下篇再寫

SQList 3封裝 http://www.itdecent.cn/p/5471d001572c

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容