iOS 之 FMDB誉简、CoreData、Plist盟广、NSUserDefault

簡(jiǎn)述

數(shù)據(jù)儲(chǔ)存可以分為數(shù)據(jù)結(jié)構(gòu)和儲(chǔ)存方式闷串。數(shù)據(jù)結(jié)構(gòu)就是數(shù)據(jù)存在的的形式。例如 NSDictionnary衡蚂、NSArray窿克、NSSet等這些簡(jiǎn)單的對(duì)象,也有像CoreData那樣的關(guān)系模型毛甲。儲(chǔ)存方式在機(jī)器內(nèi)則分為兩種:1年叮、內(nèi)存;2玻募、閃存只损。內(nèi)存存儲(chǔ)是臨時(shí)的,但是運(yùn)行速率非称哌郑快跃惫,閃存則是一種持久化存儲(chǔ),效率非常低艾栋。我們常說(shuō)的歸檔就是將內(nèi)存中的數(shù)據(jù)轉(zhuǎn)移到閃存就行持久化保存爆存。我們只有把內(nèi)存和閃存結(jié)合起來(lái)進(jìn)行操作才算完整的數(shù)據(jù)儲(chǔ)存方案。盜圖來(lái)說(shuō)明:

1.png

常見(jiàn)方式

iOS中常用的有:SQLite蝗砾、CoreData先较、Plist、NSUserDefault悼粮。

  1. NSUserDefault: 用于儲(chǔ)存配置信息
  2. SQLite: 主要用來(lái)儲(chǔ)存數(shù)量較多的小型數(shù)據(jù)
  3. CoreData: 類似SQLite闲勺,但沒(méi)SQLite那么靈活
  4. Plist: 用于存儲(chǔ)圖像、音頻等大體積數(shù)據(jù)

NSUserDefault

  1. 常規(guī)儲(chǔ)存
    NSUserDefault可以看做為APP的一個(gè)全局單例扣猫,整個(gè)APP中只有一個(gè)實(shí)例對(duì)象菜循,可以用于永久保存數(shù)據(jù),非常容易操作申尤。它支持儲(chǔ)存的數(shù)據(jù)類型有:NSNumber癌幕、NSString、NSDictionary昧穿、NSArray序芦、NSDate、BOOL粤咪。他的數(shù)據(jù)存儲(chǔ)是通過(guò)key--value一一對(duì)應(yīng)的(key必須唯一);

  2. 存儲(chǔ)自定義對(duì)象
    儲(chǔ)存小數(shù)量的自定義數(shù)據(jù)可以用NSUserDefault谚中,但是這個(gè)自定義數(shù)據(jù)必須實(shí)現(xiàn)歸檔協(xié)議,不然會(huì)存不進(jìn)去,只有轉(zhuǎn)化成NSData類型才能通過(guò)NSUserDefault儲(chǔ)存宪塔,如果是多個(gè)自定義數(shù)據(jù)可以添加到數(shù)組中磁奖,然后歸檔存儲(chǔ)到NSUserDefault中。

歸檔 解檔
//歸檔
-(void)encodeWithCoder:(NSCoder *)aCoder{
    unsigned int count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    for (int i = 0; i < count; i++) {
        const char * propertyCsString = property_getName(properties[i]);
        NSString   * propertyName  =  [NSString stringWithCString:propertyCsString encoding:NSUTF8StringEncoding];
        id           propertyValue =  [self valueForKey:propertyName];
        [aCoder encodeObject:propertyValue forKey:propertyName];
    }
    free(properties);
}

//解檔
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    if (self) {
        unsigned int count;
        objc_property_t *properties = class_copyPropertyList([self class], &count);
        for (int i = 0; i < count; i++) {
            const char *property_csNam = property_getName(properties[i]);
            NSString   *p_key = [NSString stringWithCString:property_csNam encoding:NSUTF8StringEncoding];
            id value = [aDecoder decodeObjectForKey:p_key];   
            [self setValue:value forKey:p_key];
        }   
        free(properties);
    } 
return self
} 


 ///copy 協(xié)議
-(id)copyWithZone:(NSZone *)zone{
    StudentModel *s_model = [[self copyWithZone:zone] init];
    unsigned int count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    for (int i = 0; i < count; i++) {
        const char *propertyCS = property_getName(properties[i]);
        NSString *p_key = [NSString stringWithCString:propertyCS encoding:NSUTF8StringEncoding];
        id p_value = [self valueForKey:p_key];
        [s_model setValue:p_value forKey:p_key];
    }
    free(properties);
    return s_model;
}  
  //存儲(chǔ)自定義對(duì)象
  StudentModel *s_model = [[StudentModel alloc] init];
    s_model.s_name = @"xiaoqiang";
    s_model.s_id = @"22";
    s_model.s_password = @"123456";
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:s_model];
    [u_default setObject:data forKey:@"s_student"];
    [u_default synchronize];
    NSData *rachiverData = [u_default objectForKey:@"s_student"];
    StudentModel *model = [NSKeyedUnarchiver unarchiveObjectWithData:rachiverData];
    NSLog(@"\n name is %@ \n id is %@ \n password is %@",model.s_name,model.s_id,model.s_password);  

Plist

沙盒

機(jī)制:

iOS沙盒機(jī)制就是指該APP只能訪問(wèn)自己的沙盒目錄下的文件某筐,不能訪問(wèn)其他APP的沙盒文件比搭,主要用來(lái)保存圖像、圖標(biāo)南誊、聲音身诺、屬性列表,文本等抄囚,不過(guò)iOS 8后新開(kāi)放了幾個(gè)固定系統(tǒng)區(qū)域的擴(kuò)展機(jī)制extension霉赡,它可以一定程度上解決APP之間的通信限制。

目錄
  1. Documents
    Documents主要用來(lái)保存APP運(yùn)行時(shí)需要持久化保存的數(shù)據(jù)幔托,該目錄會(huì)被iTunes同步時(shí)備份

  2. Library
    2.1 . Caches
    Caches是用來(lái)保存APP運(yùn)行時(shí)需要持久化儲(chǔ)存的數(shù)據(jù)穴亏,但不會(huì)被iTunes同步,所以該目錄適合保存一些體積大而且不需要備份的數(shù)據(jù)

    2.2. Prefrernces
    PreFrernces是用來(lái)保存應(yīng)用偏好設(shè)置的重挑,iOS的設(shè)置應(yīng)用會(huì)在該目錄中查找應(yīng)用設(shè)置的信息嗓化,也會(huì)被iTunes同步到備份

  3. tmp
    保存APP運(yùn)行時(shí)的臨時(shí)數(shù)據(jù),關(guān)閉APP后會(huì)被自動(dòng)刪除

獲取目錄方式
拼接獲让А:
 NSString *homePath = NSHomeDirectory();
 NSString *path = [homePath stringByAppendingPathComponent:@"Documents"];
 return [path stringByAppendingPathComponent:suffix]; `   
打印得到的路徑:/var/mobile/Containers/Data/Application/0FB7706E-625C-482C-B1DE-DDD241BB3220/Documents/test.plist
利用NSSearchPathForDirectoriesInDomains函數(shù)獲得Documents目錄:
 NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = pathArr[0];
    return [path stringByAppendingPathComponent:suffix];
打印得到的路徑:`  /var/mobile/Containers/Data/Application/0FB7706E-625C-482C-B1DE-DDD241BB3220/Documents/test.plist

第一個(gè)參數(shù)為代表文件路徑 一般用到NSDocumentDirectory或者NSCachesDirectory 第二個(gè)參數(shù)一般為NSUserDomainMask刺覆,第三個(gè)參數(shù)代表是否打開(kāi)一般為YES,上面PathArr 一般只能或得一個(gè)元素史煎,

補(bǔ)充

獲取沙盒tmp目錄的方法:

 NSString *tmp = NSTemporaryDirectory();

獲取沙盒caches目錄方法:

NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];

獲取應(yīng)用沙盒preference目錄的方法:

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

言歸正傳繼續(xù)plist操作筆記 plist儲(chǔ)存的數(shù)據(jù):array,dictionary,string,bool,date,data這幾種類型隅津,如果要存儲(chǔ)自定義的也要實(shí)現(xiàn)歸檔協(xié)議然后轉(zhuǎn)換成NSData類型儲(chǔ)存,plist主要用來(lái)存儲(chǔ)大文件劲室。

 NSString *path = [self getPlistLibraryWithSuffix:@"test.plist"];

    NSMutableArray *stu_array = [NSMutableArray new];
    
    for (int i = 0; i < 10; i ++) {
        
        StudentModel *s_model = [StudentModel new];
        
        s_model.s_name = [NSString stringWithFormat:@"name%d",i];
        s_model.s_id = [NSString stringWithFormat:@"%d",100 + i];
        s_model.s_password = @"123456";
        [stu_array addObject:s_model];
    }
///寫(xiě)入
    NSData *archiverData = [NSKeyedArchiver archivedDataWithRootObject:stu_array];
    BOOL isSuc = [archiverData writeToFile:path atomically:YES];
//  BOOL isSuc = [NSKeyedArchiver archiveRootObject:stu_array toFile:path];
    NSLog(@"%d",isSuc);
 
  ///讀取
    NSData *unarchiverData = [NSData dataWithContentsOfFile:path];
    NSArray *unArchiverArr = [NSKeyedUnarchiver unarchiveObjectWithData:unarchiverData];
//  NSArray *unArchiverArr = [NSKeyedUnarchiver unarchiveObjectWithFile:path];    
    NSLog(@"%@==",unArchiverArr);

SQLite:

iOS的SDK有SQLite的庫(kù),我們可以自建SQLite數(shù)據(jù)庫(kù)结窘,SQLite每次寫(xiě)入數(shù)據(jù)都會(huì)產(chǎn)生IO消耗很洋,把數(shù)據(jù)歸檔到相應(yīng)的文件。其實(shí)SQLite也跟NSUserDefaults差不多隧枫,適合儲(chǔ)存基礎(chǔ)類型的小數(shù)據(jù)喉磁,不過(guò)它更適合存儲(chǔ)大量的數(shù)據(jù),類似聊天記錄這樣的數(shù)據(jù)查詢和儲(chǔ)存官脓。SQLite的操作比較復(fù)雜协怒,因?yàn)樗皇敲嫦驅(qū)ο蟮模覀冇闷饋?lái)很不習(xí)慣卑笨,但是我們可以用第三發(fā)框架FMDB孕暇,在工程中pod FMDB 進(jìn)來(lái)。

FMDB:

  1. FMDataBase:它主要用來(lái)執(zhí)行SQL語(yǔ)句,但是它線程不安全的
  2. FMResult 用于查詢結(jié)果
  3. FMDatabaseQueue 多余多線程查詢或者更新 它是線程安全的

FMDB幾個(gè)主要的方法

FMDB中除了查詢之外都可以稱作為更新妖滔,create隧哮、delete,update座舍、insert沮翔、drop,使用executeUpdate:方法更新

更新
- (BOOL)executeUpdate:(NSString*)sql, ...
- (BOOL)executeUpdateWithFormat:(NSString*)format, ...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments;
查詢
- (FMResultSet *)executeQuery:(NSString*)sql, ...
- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
SQL語(yǔ)句
  1. 創(chuàng)建表語(yǔ)句
    create table if not exists StudentTab(numberID integer primary key not NULL ,name text,headImage blob,scroll real)

這表示如果不存在StudentTab曲秉,則創(chuàng)建一個(gè)NumberID自動(dòng)增加的的序號(hào)值采蚀,name是文本字符串類型,head為二進(jìn)制類型承二,scroll為浮點(diǎn)型類型

  1. 插入語(yǔ)句
insert into Student(name,headImage,scroll)  values (?,?,?)
insert into Student values (:name,:headImage,:scorll)榆鼠;
insert into Student(name,headImage,scroll) values('%@','%@','%lf') 
//這三句等價(jià)
  1. 更新語(yǔ)句
update Student set name = ? where scoll = ?
  1. 刪除語(yǔ)句
delete  from Student where name = ?
drop table if exists Student
  1. 查詢語(yǔ)句
select * from Student where name = ?

特殊用法:
如果你要保存的參數(shù)個(gè)數(shù)未知或者數(shù)量較多 我們可以用一下這些方法 給讓你感受到很好的體驗(yàn)

 - (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
 - (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments;

數(shù)據(jù)庫(kù)的事務(wù)也很好用 inDeferredTransaction

CoreData

  1. NSManagedObjectModel(被管理的對(duì)象模型)相當(dāng)于實(shí)體矢洲,但它也包含了實(shí)體間的關(guān)系璧眠,
  2. NSManagedObjectContext(被管理的對(duì)象上下文)操作的作用有:插入數(shù)據(jù)、查詢读虏、更新责静、刪除
  3. NSPersistentStoreCoordinator(持久化儲(chǔ)存助理)它充當(dāng)這與數(shù)據(jù)庫(kù)連接的角色
  4. NSPredicate(相當(dāng)于查詢條件)
  5. NSFetchRequest(獲取數(shù)據(jù)的請(qǐng)求)
  6. NSEntityDescription(實(shí)體結(jié)構(gòu))
  7. NSFetchedResultsController:監(jiān)聽(tīng)數(shù)據(jù)變化 實(shí)現(xiàn)代理 當(dāng)數(shù)據(jù)發(fā)生變化會(huì)盡代理
  NSFetchRequest *result = [NSFetchRequest fetchRequestWithEntityName:@"User"];`
  NSSortDescriptor * desciptor = [NSSortDescriptor sortDescriptorWithKey:@"u_name" ascending:YES];
    
    [result setSortDescriptors:@[desciptor]];

    NSManagedObjectContext *context = self.manager.mainManagedObjectContext;
    
    self.userFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:result managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
    self.userFetchedResultsController.delegate = self;  
版本遷移

coredata需要注意版本更新數(shù)據(jù)遷移處理 一般加自動(dòng)遷移處理

//自動(dòng)遷移
 NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                          [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
     abort();
 }
 return _persistentStoreCoordinator;
}  
插入
User *user = (User *)[NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:self.manager.mainManagedObjectContext];
    [user setU_age:@"26"];
    [user setU_name:@"liu"];
    [user setU_sex:@"1"];
    NSError *error ;
   BOOL isSuc =[self.manager.mainManagedObjectContext save:&error];
刪除
  NSFetchRequest *result = [[NSFetchRequest alloc] init];
    NSEntityDescription *user = [NSEntityDescription entityForName:@"User" inManagedObjectContext:self.manager.mainManagedObjectContext];
    [result setEntity:user];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"u_name = %@",@"liu"];
    [result setPredicate:predicate];    
    NSError *error = nil;
    NSArray *arr = [self.manager.mainManagedObjectContext executeFetchRequest:result error:&error]; 
    if (arr.count == 0) {
        NSLog(@"error is %@",error);
    }else{
        for (User *temp in arr) {
            [self.manager.mainManagedObjectContext deleteObject:temp];
        }
    }
    [self.manager.mainManagedObjectContext saveAndWait:YES error:&error];
更新:
 NSFetchRequest *result = [[NSFetchRequest alloc] init];    
    NSEntityDescription *user = [NSEntityDescription entityForName:@"User" inManagedObjectContext:self.manager.mainManagedObjectContext];
    [result setEntity:user];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"u_name = %@",@"liu"];
    [result setPredicate:predicate];
    NSError *erro = nil;
    NSArray *arr = [self.manager.mainManagedObjectContext executeFetchRequest:result error:&erro];
    if (arr.count == 0) {
        NSLog(@"%@ error ",erro);
    }else{
        for (User *tempUser in arr) {
            tempUser.u_age = @"18";
        }
    }
    [self.manager.mainManagedObjectContext save:&erro];
查詢
  NSFetchRequest *result = [[NSFetchRequest alloc] init];
    NSEntityDescription *user = [NSEntityDescription entityForName:@"User" inManagedObjectContext:self.manager.mainManagedObjectContext];
    
    [result setEntity:user];
    
    NSError *error ;
    
    NSMutableArray *arr = [[self.manager.mainManagedObjectContext executeFetchRequest:result error:&error] mutableCopy];
    
    if (arr.count == 0) {
        
        NSLog(@"error is %@",error);
    }
    else{
        
        for (User *tempUser in arr) {
            
            NSLog(@"%@==%@===%@",tempUser.u_name,tempUser.u_age,tempUser.u_sex);
        }
    }
線程安全處理
+(id) instanceChildManagedObjectContext {
    NSManagedObjectContext *context = nil;
    if ([NSThread isMainThread]) {
        context = [[CoreDataManager sharedCoreDataManager] mainManagedObjectContext];
    } else {
        context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        context.parentContext = [[CoreDataManager sharedCoreDataManager] mainManagedObjectContext];
    }
    return context;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市盖桥,隨后出現(xiàn)的幾起案子灾螃,更是在濱河造成了極大的恐慌,老刑警劉巖揩徊,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腰鬼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡塑荒,警方通過(guò)查閱死者的電腦和手機(jī)熄赡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)齿税,“玉大人沛申,你說(shuō)我怎么就攤上這事祠够。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵趁桃,是天一觀的道長(zhǎng)嗓违。 經(jīng)常有香客問(wèn)我瓷翻,道長(zhǎng)赖歌,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任芜壁,我火速辦了婚禮礁凡,結(jié)果婚禮上高氮,老公的妹妹穿的比我還像新娘。我一直安慰自己把篓,他們只是感情好纫溃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著韧掩,像睡著了一般紊浩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上疗锐,一...
    開(kāi)封第一講書(shū)人閱讀 51,231評(píng)論 1 299
  • 那天坊谁,我揣著相機(jī)與錄音,去河邊找鬼滑臊。 笑死口芍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的雇卷。 我是一名探鬼主播鬓椭,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼关划!你這毒婦竟也來(lái)了小染?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤贮折,失蹤者是張志新(化名)和其女友劉穎裤翩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體调榄,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡踊赠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了每庆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片筐带。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖缤灵,靈堂內(nèi)的尸體忽然破棺而出伦籍,到底是詐尸還是另有隱情,我是刑警寧澤凤价,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站拔创,受9級(jí)特大地震影響利诺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剩燥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一慢逾、第九天 我趴在偏房一處隱蔽的房頂上張望立倍。 院中可真熱鬧,春花似錦侣滩、人聲如沸口注。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)寝志。三九已至,卻和暖如春策添,著一層夾襖步出監(jiān)牢的瞬間材部,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工唯竹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乐导,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓浸颓,卻偏偏與公主長(zhǎng)得像物臂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子产上,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容