IOS學習:ios開發之數據的持久化存儲機制

IOS中數據的持久化保存這塊內容,類似於Android中文件的幾種常見的存儲方式。
對於數據的持久化存儲,ios中一般提供了4種不同的機制。
1.屬性列表
2.對象歸檔
3.數據庫存儲(SQLite3)
4.蘋果公司提供的持久性工具Core Data。


其實儲存的形式無非就這麼幾種,而我們還必須要關心的是,這些文件會被放置在那個文件下,然後如何讀取。
也就是說:IOS上數據存儲,我們要了解的兩點,數據存儲格式(也就是存儲機制),數據存儲位置。
1》文件如何存儲(如上面4點)
2》文件存儲在哪裏。
對於數據的操作,其實我們關心的是操作的速率。
就好比在Adnroid中偏好存儲,數據庫存儲,io存儲一樣。
我大致問了我們公司新來的ios哥們,他說他們培訓機構基本對數據操作這塊就講了屬性列表和數據庫,以及普通的文件存儲(比如音視頻圖這些多媒體數據)。
我就只好先看看書了。


一:應用文件目錄
首先我們來看了解下ios數據存儲位置,因爲只有知道位置路徑我們才能去讀取數據,而數據的持久化機制不過是針對操作速率來考慮的,
比如我們大致知道屬性列表(既鍵值對形式)的存儲熟慮應該高於數據庫高於io文件流存儲。
我們在選擇用何種機制存儲數據,主要也是看數據的形式。


一個ios應用安裝後大致會有如下文件夾及其對應路徑:

在mac上看模擬器中應用路徑:
/Users/nono/Library/Application Support/iPhone Simulator/5.1/Applications/2D135859-1E80-4754-B36D-34A53C521DE3

你在finder中的home下可能找不到Library這個目錄,因爲貌似是影藏起來了(我這機器上是,在終端可以看到)。
最後那一竄的類似序列號的東西就是ios自動給應用生成的一組應用唯一識別碼最爲了應用的home目錄名。
其下面就是上圖所示了。
書上對這些文件夾介紹:

Document:應用程序將其數據存儲在這個文件夾下,基於NSUserDefaults的首選項的設置除外。

簡單理解是,基本上我們要操作的一些數據都是存儲在這個文件夾下面的

TIPS:這邊提下一點,對於ios系統這麼分配文件夾,是因爲在設備進行同步時,ITunes有選擇性的意識來備份文件。

比如我們可以猜到,tmp下的應該就不會備份了。

對於Document文件夾目錄路徑的獲取,API提供了這麼一種方法:

[cpp] view plain copy
  1. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
  2.    NSString *docPath = [paths objectAtIndex:0];  

Library:基於NSUserDefault首選項設置存儲在其下Preferences文件夾中,簡單來說,這個文件夾一般你很少操作到。

書上對於這部分基本沒介紹。估計對於初級部分是跳過了。

Tmp:應用臨時存儲文件,當不需要時,應用負責刪除其下的文件數據。

該文件也提供了目錄獲取方法:

[cpp] view plain copy
  1. NSString *tmpDoc = NSTemporaryDirectory();  

應用程序文件:這個基本沒提到書上,但是我們大致可以猜測,這就是整個應用程序的程序文件夾吧。

好了,以上我們大致解決了我們提到的第一個點,文件存儲目錄


二:數據存儲機制

1.屬性列表

這個其實我們早見過,plist就是,感覺用來存儲鍵值對小數據是最合適,因爲速率很高。

這個存儲機制很簡單,對於前面我們使用過了在plist文件來讀取數據填充一些列表,只不過那會plist文件存儲位置不同,

用的是Mainbundle什麼的來返回文件夾,其實這邊我也推測,上面提到有個應用程序文件夾,它下面的文件就是這麼來讀取的~(反正暫時不管他)

這邊不過就是改變了存儲位置,數據操作還是一樣的

[cpp] view plain copy
  1. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
  2. NSString *docPath = [paths objectAtIndex:0];  
  3. NSString *myFile = [docPath stringByAppendingPathComponent:@"my.list"];  
  4. //讀取文件  
  5. NSArray *array = [[NSArray alloc] initWithContentsOfFile:myFile];  
  6. //操作完若修改了數據則,寫入文件  
  7. [array writeToFile:myFile atomically:YES];  

2.對象歸檔

上面的屬性列表存儲機制,我們都知道,這個機制支持NSArray,NSDictionary,NSData,NSString,NSNumber,NSDate 等等

這些對象直接寫入plist文件中。

那麼對於一些複雜對象,我要保存整個這個對象數據呢?

反正我是這麼覺得,這個機制很像java中的對象整體序列化。當然,這些數據在讀取是就需要遵循一種墨守成規的協議了。

首先我們定義的對象類,必須實現NSCoding和NSCopying協議(額,網上說後面這個不實現也可以,我猜是他對象沒有copy操作,因此沒出錯)書本上反正是實現了這兩個協議
然後歸檔中用到的操作類
NSKeyedArchiver
這邊我們定義一個對象,h文件中定義兩屬性,申明要實現的NSCoding和NSCopying協議
實現文件

[cpp] view plain copy
  1. //  
  2. //  TestObj.m  
  3. //  DataStorageTest  
  4. //  
  5. //  Created by Nono on 12-5-12.  
  6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.  
  7. //  
  8.   
  9. #import "TestObj.h"  
  10.   
  11. @implementation TestObj  
  12. @synthesize stringA = stringA;  
  13. @synthesize stringB = stringB;  
  14.   
  15. #pragma mark -  
  16. #pragma NSCoding協議實現實現  
  17. - (void)encodeWithCoder:(NSCoder *)aCoder  
  18. {   //encoder  
  19.     [aCoder encodeObject:stringAforKey:@"1"];  
  20.     [aCoder encodeObject:stringBforKey:@"2"];  
  21. }  
  22. - (id)initWithCoder:(NSCoder *)aDecoder  
  23. {  
  24.     //decoder  
  25.     if (self = [superinit]) {  
  26.         stringA = [[aDecoder decodeObjectForKey:@"1"] retain];  
  27.         stringB = [[aDecoder decodeObjectForKey:@"2"] retain];  
  28.     }  
  29.     returnself;  
  30. }  
  31.   
  32. #pragma NSCopying協議實現  
  33. - (id)copyWithZone:(NSZone *)zone  
  34. {  
  35.     TestObj *copy = [[[selfclass] allocWithZone:zone] init];  
  36.     copy.stringA = [[self.stringAcopyWithZone:zone] autorelease];  
  37.     copy.stringB = [[self.stringBcopyWithZone:zone] autorelease];  
  38.     return copy;  
  39. }  
  40. @end  

然後是對對象歸檔的讀取和寫入

[cpp] view plain copy
  1. //讀取歸檔文件  
  2.    NSData *data = [[NSMutableDataalloc] initWithContentsOfFile:myFile];  
  3.    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiveralloc] initForReadingWithData:data];  
  4.    TestObj * test = [unarchiver decodeObjectForKey:@"data"];  
  5.    [unarchiver finishDecoding];  
  6.    [data release];  
  7.    [unarchiver release];  
  8.      
  9.    //寫入歸檔文件  
  10.    NSMutableData *data1 = [[NSMutableDataalloc] init];  
  11.    NSKeyedArchiver *archiver = [[NSKeyedArchiveralloc] initForWritingWithMutableData:data1];  
  12.    [archiver encodeObject:test forKey:@"data"];  
  13.    [archiver finishEncoding];  
  14.    [data writeToFile:myFile atomically:YES];  
  15.    [data1 release];  
  16.    [archiver release];  
  17.    [test release];  

但是問了下新同事,據說這個用到也是蠻少,至少他目前。
但是,我看了下,覺得這個和Android 中Parcelable
太尼瑪像似了


三.數據庫存儲
和Android一樣,ios中也是用了SQLite3這種嵌入式數據庫。

這個網上例子是很多了。我這邊就大致看下了數據庫的打開,

數據庫表創建,查詢,插入

[cpp] view plain copy
  1.  //數據庫操作  
  2.  sqlite3 *database;  
  3. // const NSString * dbname = @"mydb"  
  4.  int result;  
  5.  //打開一個指定路徑的現有的數據庫,如果沒有則會新建一個db庫  
  6.  result =  sqlite3_open([myFile UTF8String], &database);  
  7.  if (result != SQLITE_OK) {  
  8.      sqlite3_close(database);  
  9.  }  
  10.    
  11.  //創建一個db表  
  12.  char *errorMsg;  
  13.  NSString *sql_create_table = @"CREATE TABLE IF NOT EXISTS NONOTABLE 省略~~~~~~~~~~~~~";  
  14.  int result1 ;  
  15.  //sqlite_exec用了針對sqlite3運行任何不要返回數據的命令,它用於執行更新,插入和刪除。簡單來說,這個方法執行的都是一些無需返回數據(雖然我們可能獲取一個狀態值。)。  
  16.  result1 = sqlite3_exec(database, [sql_create_table UTF8String], NULL, NULL, &errorMsg);  
  17.    
  18.  //檢索查詢操作  
  19.  int result2 ;  
  20.  sqlite3_stmt *statment;  
  21.  NSString *sql_selected = @"查詢語句";  
  22. result2 = sqlite3_prepare_v2(database, [sql_selected UTF8String], -1, &statment, nil);  
  23.  if(result2 == SQLITE_OK){  
  24.      //單步操作  
  25.      while (sqlite3_step(statment) == SQLITE_ROW) {  
  26.          int row = sqlite3_column_int(statment, 0);  
  27.          char * rpwData = sqlite3_column_text(statment, 1);    
  28.      }  
  29.      sqlite3_finalize(statment);  
  30.  }  
  31.    
  32.    
  33.  //綁定變量,既就是插入操作的一種變種,比如我麼那上面提到sqlite_exec可以執行插入操作,插入內容直接是寫在sql字竄裏,但是考慮到字竄涉及到無效的符號以及會一些嚴重的注入漏洞(比如以前聽過的引號符號)。  
  34.  NSString *sql_bind = @"insert into foo value(?,?)";  
  35.  result2 = sqlite3_prepare_v2(database, [sql_selected UTF8String], -1, &statment, nil);  
  36.  if(result2 == SQLITE_OK){  
  37.      sqlite3_bind_int(statment, 1, 235);  
  38.      sqlite3_bind_text(statment, 2, "test", -1, nil);  
  39.            sqlite3_finalize(statment);  
  40.  }  
  41.  if (sqlite3_step(statment) != SQLITE_DONE)  
  42.      NSLog(@"error");  
  43.  sqlite3_finalize(statment);  
  44.   
  45.   
  46.  sqlite3_close(database);  

關於更多的,大夥可以自行百度,因爲數據庫的操作語法太怪異了,書上說是基本是基於c的,本人沒學過c。看得有點心煩~


4。Core Data存儲機制

大致瀏覽下基本感覺就是將對象歸檔搞成了可視化和簡單化。

這塊內容比較多。網上資料也挺豐富的。

暫時不做介紹了。


總結下:其實對於ios數據存儲,最常用和主要要掌握的就是屬性列表和數據庫,因爲兩個是出鏡率比較高的。

其他可能在數據存明顯體現出儲優勢時,我們會去考慮用另外兩種機制。

基礎的來說,必須掌握屬性列表和sqlite的操作存儲。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章