ios數(shù)據(jù)持久化

關(guān)于數(shù)據(jù)持久化

數(shù)據(jù)持久化,字面上的意思來(lái)理解榄攀,就是將數(shù)據(jù)存放更長(zhǎng)時(shí)間嗜傅。
很顯然的,當(dāng)我們?cè)谄綍r(shí)開(kāi)發(fā)中檩赢,必然而然的會(huì)使用到數(shù)據(jù)的持久化吕嘀,但是通用的幾種方式,我們應(yīng)該了然于心贞瞒。以便于在使用到的時(shí)候币他,能夠更好的選擇使用哪一種。

通常數(shù)據(jù)持久化的幾種方式

1.NSUserDefaults
2.NSKeyedArchiver(對(duì)象模型歸檔)
3.SQLite
4.Core Data

1.NSUserDefaults

NSUserDefaults是蘋果提供的一種偏好設(shè)置的方法憔狞,將我們需要的一些偏好設(shè)置寫道plist文件當(dāng)中蝴悉。例如,記錄主題設(shè)置的模式瘾敢,是否自動(dòng)登錄等等拍冠。
NSUserDefaults是蘋果提供的一個(gè)單例,使用方法很簡(jiǎn)單簇抵,如下:

////write
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"daytime" forKey:@"themeStyle"];
[defaults synchronize];

////read
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *themeStyle= [defaults objectForKey:@"themeStyle"]

類似于此庆杜,NSUserDefaults 還持支NSData,NSString碟摆,NSNumber晃财,NSDate,NSArray典蜕,NSDictionary這些數(shù)據(jù)類型断盛。
當(dāng)然蘋果還提供了具體類型的讀寫方法:

- setBool:forKey:
- setFloat:forKey:
...等

但是,寫數(shù)據(jù)的時(shí)候特別注意的是這一句話

[defaults synchronize];

當(dāng)我們利用NSUserDefaults 來(lái)寫入數(shù)據(jù)的時(shí)候愉舔,系統(tǒng)默認(rèn)并不是馬上就會(huì)寫道plist里面钢猛,但是往往我們需要存一些偏好設(shè)置的時(shí)候,想法是寫進(jìn)去轩缤,plist里面就會(huì)馬上響應(yīng)命迈,就可以馬上讀出來(lái)贩绕。如果想實(shí)現(xiàn)該需求,就需要在我們存儲(chǔ)數(shù)據(jù)的最后面加上synchronize來(lái)同步數(shù)據(jù)到pilst里面壶愤。

2.NSKeyedArchiver與沙盒

NSKeyedArchiver 對(duì)象歸檔淑倾,就是當(dāng)我們需要將自定義的類對(duì)象進(jìn)行二進(jìn)制化歸檔。而沙盒存儲(chǔ)呢征椒,簡(jiǎn)單的來(lái)說(shuō)娇哆,就是將文件給存到本地磁盤中。

NSKeyedArchiver

首先陕靠,要使用NSKeyedArchiver歸檔,就需要實(shí)現(xiàn)NSCoding協(xié)議脱茉。同時(shí)實(shí)現(xiàn)其序列化和反序列化這兩個(gè)方法

//反序列化
//從coder中讀取數(shù)據(jù)剪芥,保存到相應(yīng)的變量中
- (id)initWithCoder:(NSCoder *)aDecoder;

// 序列化
//讀取實(shí)例變量琴许,并把這些數(shù)據(jù)寫到coder中税肪。
-(void)encodeWithCoder:(NSCoder *)coder;

沙盒

關(guān)于ios沙盒機(jī)制榜田,簡(jiǎn)單來(lái)說(shuō)就是一個(gè)安全權(quán)限益兄。默認(rèn)權(quán)限下,蘋果只允許IOS應(yīng)用程序訪問(wèn)程序自己的目錄箭券,該目錄就稱為“沙盒”净捅。
下圖是沙河目錄

MyApp.app

存放應(yīng)用程序本身的數(shù)據(jù),整個(gè)目錄是只讀的
不會(huì)被iTunes同步

Documents

存放應(yīng)用程序的數(shù)據(jù)文件(不可再生的)
會(huì)被iTunes同步

Documents/Inbox

存放保存由外部應(yīng)用請(qǐng)求當(dāng)前應(yīng)用程序打開(kāi)的文件
會(huì)被同步

Library

蘋果建議用來(lái)存放默認(rèn)設(shè)置或其它狀態(tài)信息
會(huì)被iTunes同步辩块,但是除了Caches子目錄

Library/Caches

主要是緩存文件
不會(huì)被iTunes同步

Library/Preferences

應(yīng)用程序的偏好設(shè)置文件蛔六。例如NSUserDefaults寫的設(shè)置數(shù)據(jù)都會(huì)保存到該目錄下的一個(gè)plist文件中
會(huì)被iTunes同步

tmp

各種臨時(shí)文件,保存應(yīng)用再次啟動(dòng)時(shí)不需要的文件废亭,并且隨時(shí)有可能被系統(tǒng)清理掉
不會(huì)被iTunes同步

簡(jiǎn)單的使用

了解了NSKeyedArchiver需要什么国章,沙盒是什么了,下面我們就開(kāi)始來(lái)看代碼:

@interface Person: NSObject <NSCoding>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *sex;
@end

//...
//實(shí)現(xiàn)序列化和反序列化
@implementation Person

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.sex forKey:@"sex"];
    
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
    self.name = [aDecoder decodeObjectForKey:@"name"];
    self.sex= [aDecoder decodeObjectForKey:@"sex"];
    
    return self;
}

@end

Person* person=  [[Person alloc] init];
person.name = @"zhu";
person.age = @"man";
];
//歸檔,調(diào)用encodeWithCoder方法 
NSData * perData= [NSKeyedArchiver archivedDataWithRootObject:person];
//讀取歸檔數(shù)據(jù),調(diào)用initWithCoder
Person* per= [NSKeyedUnarchiver unarchiveObjectWithData:perData];

//也可以將序列化的對(duì)象保存到沙盒中
 //獲得Document的路徑  
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];  
//拓展名可以自己隨便取
NSString *path = [documents stringByAppendingPathComponent:@"person.archiver"];   
[NSKeyedArchiver archiveRootObject:person toFile:path]; 

//讀取沙盒中的文件
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];  
NSString *path = [documents stringByAppendingPathComponent:@"person.archiver"];  
person *person1 = [NSKeyedUnarchiver unarchiveObjectWithFile:path];  


3.SQLite

SQLite是一個(gè)輕量級(jí)關(guān)系數(shù)據(jù)庫(kù),最初的設(shè)計(jì)目標(biāo)是用于嵌入式系統(tǒng),它占用資源非常少.在iOS中,只需要加入li’blibsqlite3.0依賴以及引入sqlite3.h頭文件即可豆村。
關(guān)于sqlite在ios中的使用液兽,我并沒(méi)有深入的了解過(guò),所以這里只是簡(jiǎn)單的介紹下掌动。

4.Core Data

Core Data是iOS5之后才出現(xiàn)的一個(gè)框架四啰,它提供了對(duì)象-關(guān)系映射(ORM)的功能,即能夠?qū)C對(duì)象轉(zhuǎn)化成數(shù)據(jù)粗恢,保存在SQLite數(shù)據(jù)庫(kù)文件中拟逮,也能夠?qū)⒈4嬖跀?shù)據(jù)庫(kù)中的數(shù)據(jù)還原成OC對(duì)象。
至于到底是用coredata還是sqlite适滓,大家是各持己見(jiàn)敦迄,但是我覺(jué)得還是應(yīng)該看具體的業(yè)務(wù)邏輯。不要局限于某一個(gè)工具,而是在合適的時(shí)候選擇合適的方法就好罚屋。
關(guān)于coredata我們要知道的幾個(gè)東西

1.NSManagedObjectContext(托管對(duì)象上下文)
負(fù)責(zé)應(yīng)用和數(shù)據(jù)庫(kù)之間的交互苦囱,例如增刪查改。

2.NSManagedObjectModel(托管對(duì)象模型)
負(fù)責(zé)coredara里面的模型文件

3.NSPersistentStoreCoordinator(持久化存儲(chǔ)協(xié)調(diào)器)
負(fù)責(zé)添加持久性數(shù)據(jù)庫(kù)脾猛,例如sqlite撕彤,Binary、XML猛拴、或In-Memory等羹铅。但要注意這點(diǎn),Binary和XML格式的存儲(chǔ)區(qū)是Atomic愉昆,意思是就算我們只想修改少量的數(shù)據(jù)职员,但是在保存的時(shí)候還是得將整個(gè)文件都寫進(jìn)磁盤。

對(duì)于coredata跛溉,初學(xué)者不要覺(jué)得很神奇焊切,簡(jiǎn)單的想成是一個(gè)對(duì)象關(guān)系的數(shù)據(jù)庫(kù)就行了,不需要寫sql語(yǔ)句芳室,就能實(shí)現(xiàn)數(shù)據(jù)的存取专肪。
下面是一些簡(jiǎn)單的使用:

- (IBAction)addClick:(id)sender {
    
    NSLog(@"addClick");
   
    Employee *em = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:self.ctx];
    em.name = @"lisi";
    em.height = @172;
    em.age = @25;
    
    NSError *error = nil;
    [self.ctx save:&error];
    
    if (error) {
        NSLog(@"%@===error", error);
    } else {
        NSLog(@"=====add=success====");
    }
    
}

- (IBAction)readClick:(id)sender {
    
    NSLog(@"readClick");
    
    NSEntityDescription *enty = [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:self.ctx];
    NSFetchRequest *featch = [[NSFetchRequest alloc] init];
    
    [featch setEntity:enty];
    
//    NSPredicate *pre = [NSPredicate predicateWithFormat:@"name=%@",@"lisi"];
//    
//    [featch setPredicate:pre];
    
    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"height" ascending:YES];
    featch.sortDescriptors = @[sort];
    
    NSArray *arr = [self.ctx executeFetchRequest:featch error:nil];
    for (Employee *em in arr) {
        NSLog(@"姓名:%@ 身高%@",em.name ,em.height);
    }
}


- (IBAction)deleteClick:(id)sender {
    
    NSLog(@"deleteClick");
    
    NSEntityDescription *enty = [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:self.ctx];
    NSFetchRequest *featch = [[NSFetchRequest alloc] init];
    featch.entity = enty;
    featch.predicate = [NSPredicate predicateWithFormat:@"name=%@",@"lisi"];
    
    NSArray *arr = [self.ctx executeFetchRequest:featch error:nil ];   
    for (Employee *em in arr) {
        NSLog(@"姓名:%@ 身高%@",em.name ,em.height);
        [self.ctx deleteObject:em];
    }
    
    [self.ctx save:nil];
}


- (IBAction)updateClick:(id)sender {
    
    NSLog(@"updateClick");
    
    NSEntityDescription *enty = [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:self.ctx];
    NSFetchRequest *featch = [[NSFetchRequest alloc] init];
    featch.entity = enty;
    featch.predicate = [NSPredicate predicateWithFormat:@"name=%@",@"lisi"];
    
    NSArray *arr = [self.ctx executeFetchRequest:featch error:nil ];
    
    for (Employee *em in arr) {
        NSLog(@"姓名:%@ 身高%@",em.name ,em.height);
        em.name = @"wangwu";
    }
    
    [self.ctx save:nil];
}

- (NSManagedObjectContext *)ctx
{
    if (!_ctx) {
        _ctx = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];        
                
        NSManagedObjectModel *mModel = [NSManagedObjectModel mergedModelFromBundles:nil];
        
        NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mModel];
        
        NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSString *url = [path stringByAppendingPathComponent:@"zhu.sqlite"];
        [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:url] options:nil error:nil];
        
        _ctx.persistentStoreCoordinator = coordinator;
    }
    return _ctx;
}

結(jié)束語(yǔ)

其實(shí)關(guān)于ios中數(shù)據(jù)持久化的使用,不會(huì)僅限于此堪侯,以上只是一些簡(jiǎn)單的介紹和使用的方法嚎尤。在當(dāng)說(shuō)到數(shù)據(jù)持久化的時(shí)候,我們腦海中應(yīng)該蹦出一些自己的理解來(lái)伍宦。自己心中理一個(gè)適合自己的知識(shí)結(jié)構(gòu)來(lái)幫助我們打理邏輯诺苹,然后在實(shí)際使用場(chǎng)景的時(shí)候,根據(jù)具體業(yè)務(wù)來(lái)選擇具體使用哪一種數(shù)據(jù)持久化方案雹拄。我認(rèn)為做開(kāi)發(fā)的不要一腦門的死記硬背收奔,一腦門的按照別人的說(shuō)的來(lái)做∽揖粒看到別人的邏輯的時(shí)候坪哄,覺(jué)得好的,自己心里領(lǐng)會(huì)下势篡,覺(jué)得不好的翩肌,自己在想想怎么去做會(huì)更加完美。千萬(wàn)不要做代碼的奴隸禁悠,而是以一種藝術(shù)家念祭,建筑師又或者設(shè)計(jì)師的角度來(lái)審視代碼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末碍侦,一起剝皮案震驚了整個(gè)濱河市粱坤,隨后出現(xiàn)的幾起案子隶糕,更是在濱河造成了極大的恐慌,老刑警劉巖站玄,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枚驻,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡株旷,警方通過(guò)查閱死者的電腦和手機(jī)再登,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)晾剖,“玉大人锉矢,你說(shuō)我怎么就攤上這事〕菥。” “怎么了沽损?”我有些...
    開(kāi)封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)雕什。 經(jīng)常有香客問(wèn)我缠俺,道長(zhǎng)显晶,這世上最難降的妖魔是什么贷岸? 我笑而不...
    開(kāi)封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮磷雇,結(jié)果婚禮上偿警,老公的妹妹穿的比我還像新娘。我一直安慰自己唯笙,他們只是感情好螟蒸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著崩掘,像睡著了一般七嫌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上苞慢,一...
    開(kāi)封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天诵原,我揣著相機(jī)與錄音,去河邊找鬼挽放。 笑死绍赛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辑畦。 我是一名探鬼主播吗蚌,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纯出!你這毒婦竟也來(lái)了蚯妇?” 一聲冷哼從身側(cè)響起敷燎,我...
    開(kāi)封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侮措,沒(méi)想到半個(gè)月后懈叹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡分扎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年澄成,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畏吓。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡墨状,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出菲饼,到底是詐尸還是另有隱情肾砂,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布宏悦,位于F島的核電站镐确,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏饼煞。R本人自食惡果不足惜源葫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望砖瞧。 院中可真熱鬧息堂,春花似錦、人聲如沸荣堰。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)斋扰。三九已至渡八,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間褥实,已是汗流浹背呀狼。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工损离, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人僻澎。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓貌踏,卻偏偏與公主長(zhǎng)得像十饥,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子祖乳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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

  • iOS數(shù)據(jù)持久化方式 文件 歸檔(NSKeyedArchiver) 屬性列表(NSUserDefaults) 數(shù)據(jù)...
    向陽(yáng)的向日葵花閱讀 901評(píng)論 0 12
  • 1.簡(jiǎn)介 數(shù)據(jù)持久存儲(chǔ)是一種非易失性存儲(chǔ)眷昆,在重啟動(dòng)計(jì)算機(jī)或設(shè)備后也不會(huì)丟失數(shù)據(jù)。持久化技術(shù)主要用于MVC模型中的m...
    公子無(wú)禮閱讀 1,680評(píng)論 0 4
  • 前言: 在程序開(kāi)發(fā)中作媚,數(shù)據(jù)層永遠(yuǎn)是程序的核心結(jié)構(gòu)之一帅刊。對(duì)這些數(shù)據(jù)的加工處理是代碼中能體現(xiàn)技術(shù)水平的一大模塊,比如數(shù)...
    麥穗0615閱讀 1,459評(píng)論 3 22
  • IOS數(shù)據(jù)持久化 數(shù)據(jù)的持久化女揭,就是將數(shù)據(jù)保存到硬盤中,使得在應(yīng)用程序或機(jī)器重啟后可以繼續(xù)訪問(wèn)之前保存的數(shù)據(jù)吧兔。在i...
    koula閱讀 1,158評(píng)論 0 19
  • Title: iOS數(shù)據(jù)持久化 ##數(shù)據(jù)持久化概念 數(shù)據(jù)持久化就是將內(nèi)存中的數(shù)據(jù)模型轉(zhuǎn)換為存儲(chǔ)模型抡爹,以及將存儲(chǔ)模型...
    barrylyl閱讀 934評(píng)論 0 3