iOS應用開發視頻教程筆記(十二)Persistence

來源:互聯網
上載者:User

這節課主要講幾個部分,一個是final project的準則,然後是持久化(Persistence)問題。

Persistence

持久化(Persistence)意思就是當你退出app的時候它還會存在。NSUserDefaults就是一個非常簡單的持久化方案,不過這有限制,它只能是很小的東西,通常是些使用者選項。

如何把那些大資料的東西持久化?

第一個方法,把東西持久化的第一個簡單的方式有點像用NSUserDefaults裡的property list來實現的進化版,property list是我們自訂的一個概念,是NSArray、NSDictionary、NSNumber、NSString、 NSDate和NSData的組合。所有以上這些都有API可以用來儲存,NSUserDefaults也有些API可以。

NSData、NSArray和NSDictionary裡還有很重要的方法writeToURL:atomically:,這個方法就是把一個array寫到一個檔案系統中URL表示的地方,atomically就是如果檔案已經存在,它會把檔案移到一邊,然後寫到一個新的檔案,關掉這個新的檔案。實際上就是寫到一個臨時命名的檔案,然後關掉,把另一個移走,有點原子化操作的感覺,不能寫到一半就停下來。writeToURL之後,為了把東西取回來,可以用initWithContentsOfURL或者dataWithContentsOfURL。這些讀寫方法,不管是發送到NSData或者NSArray或者NSDictionary,就是想讓一個相同類型的對象去讀回來,它的內部可以就是些property
list的東西。

還有另一個類叫做NSPropertyListSerialization,它所做的事情就是把property list轉化成NSData,反之亦然。這樣它可以將property list轉化成一堆位元,然後就可以寫到磁碟上,或儲存到網路。也可以通過網路讀取一堆位元再通過NSPropertyListSerialization把它們轉化回property list。

關於儲存的另外一個方法就是通過對象的映像圖(arbitrary graphs)來進行歸檔對象(Archiving Objects)的儲存。

把東西儲存到檔案系統當中。

然後是SQLite

關於持久化儲存的重頭部分就是Core Data,這是在SQL上層的一個物件導向的資料庫機制。

Archiving

在做對象圖歸檔的時候有很多陷阱,歸檔很適合做循環圖表。Archiving能發現指標實際所指的對象或者指標相互指著,然後當unarchives的時候又恢複那個指標。但你要考慮清楚來使你構建的對象圖有意義,最好的例子可能是在xcode裡面建立的view層級。

當從物件程式庫中拖一些東西到螢幕上,就是在執行個體化UIView,執行個體化UIViewController,它們都是generic的,所以才需要去inspector面板來改變它們的類。

基本上就是在這個圖裡面的對象都必須實現NSCoding這個protocol,然後這個protocol裡面有兩個重要方法:

- (void)encodeWithCoder:(NSCoder *)coder; - initWithCoder:(NSCoder *)coder;

第一個是把自己放進archive,第二是把你從archive中取出來用的。這就是viewController出現在storyboard時不用調用它們的指定初始化的原因,因為它們用了這套初始化。這套歸檔系統在對它們做alloc initWithCoder,因為它們之前用encodeWithCoder把自己儲存起來了。在UIView裡沒有調用initWithFrame,而是用frame對應的encodeWithCoder和initWithCoder來代替。

- (void)encodeWithCoder:(NSCoder *)coder {      [super encodeWithCoder:coder];      [coder encodeFloat:scale forKey:@“scale”];      [coder encodeCGPoint:origin forKey:@“origin”];      [coder encodeObject:expression forKey:@“expression”];}

必須保證initWithCoder和encodeWithCoder是相對應的。

- initWithCoder:(NSCoder *)coder {      self = [super initWithCoder:coder];      scale = [coder decodeFloatForKey:@“scale”];      expression = [coder decodeObjectForKey:@“expression”];      origin=[coderdecodeCGPointForKey:@“origin”]; //notethatorderdoesnotmatter}

怎麼來實現這些呢?NSKeyedArchiver中的類方法:

+ (NSData *)archivedDataWithRootObject:(id <NSCoder>)rootObject;

可以傳遞一個根對象,比如在storyboard裡面的根對象就可能是頂層的view controller。你要做的就是確保裡面所有的對象都實現NSCoder協議。

NSKeyedUnarchiver中的類方法:

+ (id <NSCoder>)unarchiveObjectWithData:(NSData *)data;

這正好相反,你提供一個已經歸檔的NSData,然後返回被encode的根對象。

id <NSCoder> object = ...; NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object]; id <NSCoder> dup = [NSKeyedArchiver unarchiveObjectWithData:data];

如果有一個對象,通過第二行將得到關於這個對象的NSData。

如果encode一個view使它的super view被歸檔,你會被拒絕,除非它處於正確的層級,如果它在頂部它會被拒絕,但如果在內部,就會執行。

File System

ios是基於Unix的,底層都是Unix的檔案系統,這裡有檔案系統保護,不可能看到所有的東西,而且也不能隨意的寫入。

只能在sandbox中做寫入,為什嗎?為了安全。當在裝置上刪除app時,也會刪除所有相關的資料。通過在sandbox中進行寫操作,所有應用程式的東西不管是使用者建立的還是應用程式自己在sandbox裡面建立的一旦移除,所有的都會被移除。

sandbox到底是什嗎?這裡面有應用程式的bundle目錄,應用程式不是單獨的大的二進位檔案,它實際上是一個目錄,裡面有可執行程式、二進位檔案、storyboard及拖進來的圖片,所有東西都在裡面,這就是應用程式的bundle。sandbox裡的目錄本身是不可寫的,不能在目錄裡寫入東西。這基本上就是一個用xcode建立的app的唯讀副本。documents目錄是sandbox中的一個重要目錄,這些地方是用來儲存那些被使用者視為是自己的文檔的。還有一個緩衝目錄,這裡都是一些我們寫出來的東西,使用者一般不會認為這些是文檔,而且這些文檔的存在都很短暫,沒有了也不會影響到使用者。documentation裡的關鍵東西是NSSearchPathDirectory。

如何才能得到這些目錄,如何得到這些目錄的URL?如果想在application目錄中寫入,但又不能寫入,那麼要做的就是將application包裡面的東西拷貝到sandbox中任意一個可寫的地方然後在那裡寫入。如果你想將一個資料庫連接到你的app,或寫入那些資料庫,得將它們拷貝出來,無論是拷到文檔目錄,或是緩衝目錄,總之是可以寫入了。

如何搞到這些目錄的路徑呢?使用這個方法:

- (NSArray *)URLsForDirectory:(NSSearchPathDirectory)directory                        inDomains:(NSSearchPathDomainMask)domainMask; //NSUserDomainMask

NSURL中有個API可以獲得一個URL的清單,但得傳入想要的目錄類型,譬如文檔目錄、緩衝目錄。以上方法和NSURL的方法,它們返回一個路徑的array,所以當我請求緩衝目錄時,將得到一個URL的array,或是路徑字串的數組。

NSFileManager為檔案系統提供實用操作,這不是用來讀寫它們自身檔案的類。你可以用它來找出檔案到底有多大,刪除那些陳舊的需要被踢出的快取檔案,也可以用它來找出譬如當應用程式啟動時,緩衝裡面都有哪些檔案。它是安全執行緒的,只要不在兩個不同的線程中使用同一個執行個體。

NSString也有一些檔案系統有關的東西,特別是製作路徑,一般用NSURL來指定一個連結,有時會用字串來構建URL。

- (NSString *)stringByAppendingPathComponent:(NSString *)component;

這可以在一個路徑中新增內容。還可以把字串的內容寫到檔案裡去,必須要指定用哪種編碼,譬如ASCII、ISOLatin1,

- (BOOL)writeToFile:(NSString *)path         atomically:(BOOL)flag            encoding:(NSStringEncoding)encoding //e.g.ASCII,ISOLatin1,etc.              error:(NSError **)error;

也可以從檔案讀取string:

- (NSString *)stringWithContentsOfFile:(NSString *)path                          usedEncoding:(NSStringEncoding *)encoding                                  error:(NSError **)error;
SQLite

SQLite是指SQL檔案儲存在單一一個檔案裡,儲存在一個單一的檔案中,它速度很快,只佔用很小的記憶體。它基於交易處理,是真正的SQL。這不是基於伺服器的SQL,而是基於檔案的,所以它是並發性的。如果app中有兩個線程,都要寫入到SQL資料庫中,這可以正常運行。但它只是做簡單的鎖線程和並發。

以下就是它的API:

intsqlite3_open(constchar*filename,sqlite3**db); //get a database into db int sqlite3_exec(sqlite3 *db,    // execute SQL statements                 const char *sql,                  int (*callback)(void *, int, char **, char **),                  void *context,                  char **error);int mycallback(void *context,int count,char **values,char **cols); //data returned int sqlite3_close(sqlite3 *db);    // close the database

當你開啟SQL檔案時,你會得到一個SQL資料庫指標,然後要執行SQL語句。向資料庫遞交你的SQL語句,一些SQL語句就會回調然後在一張表中將你請求的資料返回給你,返回的也可能是error。回呼函數通常是這樣的格式:

int mycallback(void *context,int count,char **values,char **cols);

然後就可以關閉了。你要做的就是第三行const char *sql,這是執行SQL語句的地方。

原文:點擊開啟連結

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.