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

在iOS開發(fā)中必不可少的要用到數(shù)據(jù)存儲,數(shù)據(jù)的處理是iOS開發(fā)中的核心技術(shù),適當(dāng)?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)
由于偏好設(shè)置是將所有數(shù)據(jù)保存到preference目錄下的一個以此應(yīng)用包名來命名的plist文件中,所以將偏好設(shè)置和屬性列表放到一塊介紹。

沙盒機制

iOS應(yīng)用程序只能在為改程序創(chuàng)建的文件系統(tǒng)中讀取文件,不可以去其他地方訪問,此區(qū)域被稱為沙盒,所以所有的非代碼文件都要保持在此,例如圖像,圖標(biāo),聲音,屬性列表,文本文件等。
1、目錄結(jié)構(gòu)

1、NSBundle
2、Documents
3、Library
      Caches
      Preferences
4、tmp

2、目錄結(jié)構(gòu)分析

  • 應(yīng)用程序包:包含所有的資源文件和可執(zhí)行文件
NSString *path = [[NSBundle mainBundle]  bundlePath];
  • Documents:保存應(yīng)?運行時生成的需要持久化的數(shù)據(jù),iTunes同步設(shè)備時會備份該目錄。
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [path objectAtIndex:0];
  • Library/Caches: iTunes不會同步此文件夾,適合存儲體積大,不需要備份的非重要數(shù)據(jù)。
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSLog(@"%@", path);
  • Library/Preferences: iTunes同步該應(yīng)用時會同步此文件夾中的內(nèi)容,通常保存應(yīng)用的設(shè)置信息。
  • tmp: iTunes不會同步此文件夾,系統(tǒng)可能在應(yīng)用沒運行時就刪除該目錄下的文件,所以此目錄適合保存應(yīng)用中的一些臨時文件,用完就刪除
NSString *path = NSTemporaryDirectory();
NSLog(@"%@", path);

1.屬性列表(plist)

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

將數(shù)據(jù)寫入plist文件
  • 創(chuàng)建文件
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [path objectAtIndex:0];
NSString *myFile = [docPath stringByAppendingPathComponent:@"yourFile.plist"];
  • 寫入文件
NSArray *array = @[@"1", @"2", @"3"];
[array writeToFile:fileName atomically:YES];
  • 讀取文件
NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
NSDictionary * result = [NSDictionary dictionaryWithContentsOfFile:fileName];
NSLog(@"%@", result);
文件目錄中plist文件(包括info.plist)
//1、獲取文件所在的路徑,Resource:文件名稱、Type:文件格式
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"userInfos" ofType:@"plist"];
// 2、從路徑中獲取對應(yīng)格式的數(shù)據(jù)
// 如果Root為NSArray,則使用數(shù)組保存
NSArray *infos = [NSArray arrayWithContentsOfFile:filePath];
NSLog(@"%@",infos);
// 如果Root為NSDictionary,則使用字典保存
NSDictionary *infoDic = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSLog(@"%@",infoDic);

2. 偏好設(shè)置(NSUserDefault)

創(chuàng)建
@property (class, readonly, strong) NSUserDefaults *standardUserDefaults;

可存儲的數(shù)據(jù)類型
* NSObject(NSArray、NSDictionary、NSData)
* NSString
* NSUrl
* NSInteger、float、double、BOOL

清空存儲數(shù)據(jù)
- (void)removeObjectForKey:(NSString *)defaultName;//清空單個數(shù)據(jù)
+ (void)resetStandardUserDefaults;//重置所有數(shù)據(jù)

3.歸檔

歸檔是一種很常用的文件儲存方法,幾乎任何類型的對象都能夠被歸檔儲存(實際上是一種文件保存的形式),與屬性列表相反,同樣作為輕量級存儲的持久化方案,數(shù)據(jù)歸檔是進行加密處理的,數(shù)據(jù)在經(jīng)過歸檔處理會轉(zhuǎn)換成二進制數(shù)據(jù),所以安全性要遠(yuǎn)遠(yuǎn)高于屬性列表。我們可以將復(fù)雜的對象寫入文件中,并且不管添加多少對象,將對象寫入磁盤的方式都是一樣的。

  • 使用archiveRootObject進行簡單的歸檔
歸檔類型:字符串、數(shù)字、NSDictionary、NSArray
//1.獲取文件路徑
NSString *docPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//2、添加儲存的文件名
NSString *path  = [docPath stringByAppendingPathComponent:@"data.archiver"];
//3、將一個對象保存到文件中
BOOL flag = [NSKeyedArchiver archiveRootObject:@”name” toFile:path];
  • 將多個對象進行歸檔
    歸檔:寫入數(shù)據(jù)
//準(zhǔn)備數(shù)據(jù)
CGPoint point = CGPointMake(1.0, 2.0);
NSString *origin = @"坐標(biāo)原點";
NSInteger value = 10;
NSString *docPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path = [docPath stringByAppendingPathComponent:@"multi.archiver"];
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archvier = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//對多個對象進行歸檔
[archvier encodeCGPoint:point forKey:@"kPoint"];
[archvier encodeObject: origin forKey:@"kOrigin"];
[archvier encodeInteger:value forKey:@"kValue"];
[archvier finishEncoding];
[data writeToFile:path atomically:YES];

解檔:從路徑中獲得數(shù)據(jù)構(gòu)造NSKeyedUnarchiver實例,使用encodeObject: forKey:方法獲得文件中的對象。

NSMutableData *data = [[NSMutableData alloc] initWithContentsOfFile:multiHomePath];  
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];  
CGPoint point = [unarchiver decodeCGPointForKey:@"kPoint"];  
NSString *info = [unarchiver decodeObjectForKey:@"kInfo"];  
NSInteger value = [unarchiver decodeIntegerForKey:@"kValue"];  
[unarchiver finishDecoding];  
NSLog(@"%f,%f,%@,%d",point.x,point.y,info,value);
  • 對自定義對象進行歸檔
    //創(chuàng)建模型
#import <Foundation/Foundation.h>
// 如果想將一個自定義對象保存到文件中必須實現(xiàn)NSCoding協(xié)議
@interface Person : NSObject<NSCoding>
//姓名
@property(nonatomic,copy)NSString *name;
//年齡
@property(nonatomic,assign)int age;
@end
#import "Person.h"
@implementation Person
// 當(dāng)將一個自定義對象保存到文件的時候就會調(diào)用該方法
// 在該方法中說明如何存儲自定義對象的屬性
// 也就說在該方法中說清楚存儲自定義對象的哪些屬性
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    NSLog(@"調(diào)用了encodeWithCoder:方法");
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInteger:self.age forKey:@"age"];
    [aCoder encodeDouble:self.height forKey:@"height"];
}

// 當(dāng)從文件中讀取一個對象的時候就會調(diào)用該方法
// 在該方法中說明如何讀取保存在文件中的對象
// 也就是說在該方法中說清楚怎么讀取文件中的對象
- (id)initWithCoder:(NSCoder *)aDecoder
{
    //注意:在構(gòu)造方法中需要先初始化父類的方法
    if (self=[super init]) {
        self.name=[aDecoder decodeObjectForKey:@"name"];
        self.age=[aDecoder decodeIntegerForKey:@"age"];
    }
    return self;
}
@end

歸檔

//1.創(chuàng)建對象
Person *person = [[YYPerson alloc] init];
person.name=@"蝸牛";
person.age=23;
person.height=1.83;

//2.獲取文件路徑
NSString *docPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
 NSString *path=[docPath stringByAppendingPathComponent:@"person.archiver"];
NSLog(@"path=%@",path);

    //3.將自定義的對象保存到文件中,調(diào)用NSKeyedArchiver的工廠方法 archiveRootObject: toFile: 方法
 [NSKeyedArchiver archiveRootObject:p toFile:path];

解檔

//1.獲取文件路徑
NSString *docPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
 NSString *path=[docPath stringByAppendingPathComponent:@"person.archiver"];
 NSLog(@"path=%@",path);
 //2.從文件中讀取對象,解檔對象就調(diào)用NSKeyedUnarchiver的一個工廠方法 unarchiveObjectWithFile: 即可。
 Person * person = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

SQList 3 (FMDB)

FMDB框架中重要的框架類

  • FMDatabase
    FMDatabase對象就代表一個單獨的SQLite數(shù)據(jù)庫,用來執(zhí)行SQL語句
  • FMResultSet
    使用FMDatabase執(zhí)行查詢后的結(jié)果集
  • FMDatabaseQueue
    用于在多線程中執(zhí)行多個查詢或更新,它是線程安全的

數(shù)據(jù)庫使用

  • 1.使用FMDataBase類建立數(shù)據(jù)庫
  //1.獲得數(shù)據(jù)庫文件的路徑
  NSString *doc =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)  lastObject];                  

  NSString *fileName = [doc stringByAppendingPathComponent:@“student.sqlite”];

   //2.獲得數(shù)據(jù)庫
   FMDatabase *db = [FMDatabase databaseWithPath:fileName];

 //3.使用如下語句,如果打開失敗,可能是權(quán)限不足或者資源不足。通常打開完操作操作后,需要調(diào)用 close 方法來關(guān)閉數(shù)據(jù)庫。在和數(shù)據(jù)庫交互 之前,數(shù)據(jù)庫必須是打開的。如果資源或權(quán)限不足無法打開或創(chuàng)建數(shù)據(jù)庫,都會導(dǎo)致打開失敗。
 if ([db open])
  {
        //4.創(chuàng)表
      BOOL result = [db executeUpdate:@“CREATE TABLE IF NOT EXISTS t_student (id integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL, age integer NOT NULL);”];
       if (result)
        {
          NSLog(@“創(chuàng)建表成功”);
        }
  }
  • 2.使用FMDataBase類執(zhí)行數(shù)據(jù)庫插入命令SQLinsert into
  int age = 42;

 //1.executeUpdate:不確定的參數(shù)用?來占位(后面參數(shù)必須是oc對象,;代表語句結(jié)束)
 [self.db executeUpdate:@“INSERT INTO t_student (name, age) VALUES (?,?);”,name,@(age)];

    //2.executeUpdateWithForamat:不確定的參數(shù)用%@,%d等來占位 (參數(shù)為原始數(shù)據(jù)類型,執(zhí)行語句不區(qū)分大小寫)
 [self.db executeUpdateWithForamat:@“insert into t_student (name,age) values (%@,%i);”,name,age];

    //3.參數(shù)是數(shù)組的使用方式
 [self.db executeUpdate:@“INSERT INTO     
 t_student(name,age) VALUES  (?,?);”withArgumentsInArray:@[name,@(age   
  • 3.使用FMDataBase類執(zhí)行數(shù)據(jù)庫刪除命令SQLdelete
  //1.不確定的參數(shù)用?來占位 (后面參數(shù)必須是oc對象,需要將int包裝成OC對象)
  int idNum = 101;
    [self.db executeUpdate:@“delete from t_student where id = ?;”,@(idNum)];

   //2.不確定的參數(shù)用%@,%d等來占位
    [self.db executeUpdateWithFormat:@“delete from t_student where name = %@;”,@“apple_name”];
  • 4.使用FMDataBase類執(zhí)行數(shù)據(jù)庫修改命令SQLupdate
  //修改學(xué)生的名字
  [self.db executeUpdate:@“update t_student set name = ? where name = ?”,newName,oldName];
  • 5.使用FMDataBase類執(zhí)行數(shù)據(jù)庫查詢命令SQLselect ... from
    SELECT命令就是查詢,執(zhí)行查詢的方法是以-excuteQuery開頭的。執(zhí)行查詢時,如果成功返回FMResultSet對象,錯誤返回nil。與執(zhí)行更新相當(dāng),支持使用NSError參數(shù)。同時,你也可以使用-lastErrorCode和-lastErrorMessage獲知錯誤信息。
  • FMResultSet獲取不同數(shù)據(jù)格式的方法
    • intForColumn:
    • longForColumn:
    • longLongIntForColumn:
    • boolForColumn:
    • doubleForColumn:
    • stringForColumn:
    • dataForColumn:
    • dataNoCopyForColumn:
    • UTF8StringForColumnIndex:
    • objectForColumn:
 //查詢整個表
FMResultSet *resultSet = [self.db execute Query:@“select * from t_student;”];

 //根據(jù)條件查詢
FMResultSet *resultSet = [self.db executeQuery:@“select * from t_student where id<?;”@(14)];

 //遍歷結(jié)果集合   
while ([resultSet  next])
   {
    int idNum = [resultSet intForColumn:@“id”];
    NSString *name = [resultSet    
    objectForColumn:@“name”];
    int age = [resultSet intForColumn:@“age”];
  }
  • 6.使用FMDataBase類執(zhí)行數(shù)據(jù)庫銷毀命令SQLdrop ...
  //如果表格存在 則銷毀
  [self.db executeUpadate:@“drop table if exists t_student;”];
最后編輯于
?著作權(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)容

  • [TOC] 一、應(yīng)用的文件結(jié)構(gòu) I. 應(yīng)用沙盒 每個iOS應(yīng)用都有一個 應(yīng)用沙盒「文件系統(tǒng)目錄」,與其他文件系統(tǒng)隔...
    _涼風(fēng)_閱讀 1,686評論 2 8
  • iOS應(yīng)用數(shù)據(jù)存儲的常用方式 XML屬性列表(plist)歸檔2.Preference(偏好設(shè)置)3.NSKeye...
    清風(fēng)沐沐閱讀 405評論 0 1
  • 前言 在iOS開發(fā)中必不可少的要用到數(shù)據(jù)存儲,數(shù)據(jù)的處理是iOS開發(fā)中的核心技術(shù),適當(dāng)?shù)膶?shù)據(jù)進行持久化存儲可以實...
    若小北00閱讀 8,235評論 6 28
  • 數(shù)據(jù)存儲 iOS應(yīng)用數(shù)據(jù)存儲的常用方式 - XML屬性列表(plist)歸檔 - Preference(偏好設(shè)置)...
    Hevin_Chen閱讀 261評論 0 0
  • 1.1市場調(diào)研 市場調(diào)研是指研究市場以了解客戶需求、競爭狀況及市場力量(market forces),其最終目標(biāo)是...
    冰炫閱讀 326評論 0 1

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