軟體中永遠繞不開的一個問題就是資料存儲的問題,PC的時候一般都是選擇在資料庫中存儲,iOS如果是和後端配合的話,那麼不需要考慮資料存儲的這個問題,上次寫了一下plist的存儲,不過資料都是存儲一些簡單的鍵值對對象。本次需要将一些自己定義的類型存儲在plist比如說圖檔,這個時候可以利用NSCoding協定,将資料地以類似檔案的形式存儲到plist檔案中,然後從plist的檔案中讀取資料,使用協定的時候這個時候就會用到了NSCoder,如果對存檔和解壓沒有概念的話,可以簡單的了解為資料的序列化與反序列化。
NSCoding是一個protocol. 如果實作了NSCoding,需要實作其中的兩個方法:
1
2
<code>- (</code><code>void</code><code>)encodeWithCoder:(</code><code>NSCoder</code> <code>*)aCoder;</code>
<code>- (</code><code>id</code><code>)initWithCoder:(</code><code>NSCoder</code> <code>*)aDecoder; </code><code>// NS_DESIGNATED_INITIALIZER</code>
方法中的主要的參數就是NSCoder,它是archivie位元組流的抽象類.可以将資料寫入一個coder,也可以從coder中讀取我們寫入的資料. NSCoder是一個抽象類,不能直接使用它來建立對象. 但是可以通過其子類NSKeyedUnarchiver從位元組流中讀取資料,NSKeyedArchiver将對象寫入到位元組流。本文以書籍為例:
建立一個Book類,Book.h中的代碼:
3
4
5
6
7
8
9
10
11
12
13
14
<code>#import <Foundation/Foundation.h></code>
<code>#import <UIKit/UIKit.h></code>
<code>@interface</code> <code>Book : </code><code>NSObject</code><code><</code><code>NSCoding</code><code>></code>
<code>@property</code> <code>(strong,</code><code>nonatomic</code><code>) UIImage *ConverPicture;</code>
<code>@property</code> <code>(strong,</code><code>nonatomic</code><code>) </code><code>NSString</code> <code>*BookName;</code>
<code>@property</code> <code>(strong,</code><code>nonatomic</code><code>) </code><code>NSString</code> <code>*Author;</code>
<code>@property</code> <code>(strong,</code><code>nonatomic</code><code>) </code><code>NSNumber</code> <code>*Price;</code>
<code>@end</code>
Book.m中實作NSCoding的兩個方法,注意中UIImage的寫法與其他有所不同:
15
16
17
18
19
20
21
22
<code>@implementation</code> <code>Book</code>
<code>- (</code><code>void</code><code>)encodeWithCoder:(</code><code>NSCoder</code> <code>*)aCoder{</code>
<code> </code>
<code> </code><code>//注意這裡是存儲的是JPG圖檔的調用</code>
<code> </code><code>[aCoder encodeObject:UIImageJPEGRepresentation(</code><code>self</code><code>.ConverPicture,1.0)forKey:@</code><code>"ConverPicture"</code><code>];</code>
<code> </code><code>[aCoder encodeObject:_BookName forKey:@</code><code>"BookName"</code><code>];</code>
<code> </code><code>[aCoder encodeObject:_Author forKey:@</code><code>"Author"</code><code>];</code>
<code> </code><code>[aCoder encodeObject:_Price forKey:@</code><code>"Price"</code><code>];</code>
<code>}</code>
<code>- (</code><code>id</code><code>)initWithCoder:(</code><code>NSCoder</code> <code>*)aDecoder{</code>
<code> </code><code>self</code><code>.ConverPicture=[UIImage imageWithData:[aDecoder decodeObjectForKey:@</code><code>"ConverPicture"</code><code>]];</code>
<code> </code><code>self</code><code>.BookName=[aDecoder decodeObjectForKey:@</code><code>"BookName"</code><code>];</code>
<code> </code><code>self</code><code>.Author=[aDecoder decodeObjectForKey:@</code><code>"Author"</code><code>];</code>
<code> </code><code>self</code><code>.Price=[aDecoder decodeObjectForKey:@</code><code>"Price"</code><code>];</code>
<code> </code><code>return</code> <code>self</code><code>;</code>
正常的情況的不需要建立頁面的,不過需要示範一下UIImage的效果,Main.storyboard中的布局:

稍微解釋一下,前兩個是存的單檔案,後兩個存的是多檔案,UIImage展示存儲的圖檔:
ViewController定義字段:
<code>@property</code> <code>(strong,</code><code>nonatomic</code><code>) </code><code>NSString</code> <code>*storagePath;</code>
<code>@property</code> <code>(strong,</code><code>nonatomic</code><code>) </code><code>NSString</code> <code>*storageListPath;</code>
<code>@property</code> <code>(strong,</code><code>nonatomic</code><code>) </code><code>NSMutableArray</code> <code>*bookList;</code>
設定路徑,如果不是很清晰,可參考本文之前的部落格:
<code>NSArray</code> <code>*codepath= </code><code>NSSearchPathForDirectoriesInDomains</code><code>(</code><code>NSDocumentDirectory</code><code>, </code><code>NSUserDomainMask</code><code>, </code><code>YES</code><code>);</code>
<code> </code><code>_storagePath = [codepath[0] stringByAppendingPathComponent:@</code><code>"book.plist"</code><code>];</code>
<code> </code><code>NSLog</code><code>(@</code><code>"%@"</code><code>,</code><code>NSHomeDirectory</code><code>());</code>
<code> </code><code>_storageListPath = [codepath[0] stringByAppendingPathComponent:@</code><code>"booklist.plist"</code><code>];</code>
單個存檔:
<code>Book *book=[[Book alloc]init];</code>
<code> </code><code>UIImage *image=[UIImage imageNamed:@</code><code>"Code1.jpg"</code><code>];</code>
<code> </code><code>book.ConverPicture=image;</code>
<code> </code><code>book.BookName=@</code><code>"百年孤獨"</code><code>;</code>
<code> </code><code>book.Author=@</code><code>"加西亞.馬爾克斯"</code><code>;</code>
<code> </code><code>book.Price=[[</code><code>NSNumber</code> <code>alloc] initWithInteger:45];</code>
<code> </code><code>if</code> <code>([</code><code>NSKeyedArchiver</code> <code>archiveRootObject:book toFile:_storagePath]) {</code>
<code> </code><code>NSLog</code><code>(@</code><code>"資料存檔成功"</code><code>);</code>
<code> </code><code>}</code>
單個解壓:
<code>Book *decodeBook=[</code><code>NSKeyedUnarchiver</code> <code>unarchiveObjectWithFile:_storagePath];</code>
<code> </code><code>self</code><code>.myImageView.image=decodeBook.ConverPicture;</code>
<code> </code><code>NSLog</code><code>(@</code><code>"%@"</code><code>,decodeBook.ConverPicture);</code>
<code> </code><code>NSLog</code><code>(@</code><code>"%@"</code><code>,decodeBook.BookName);</code>
<code> </code><code>NSLog</code><code>(@</code><code>"解檔成功"</code><code>);</code>
多個存檔:
<code>self</code><code>.bookList=[</code><code>NSMutableArray</code> <code>array];</code>
<code> </code><code>for</code> <code>(</code><code>NSInteger</code> <code>i=1; i<3; i++) {</code>
<code> </code><code>Book *book=[[Book alloc]init];</code>
<code> </code><code>NSString</code> <code>*imageName=[</code><code>NSString</code> <code>stringWithFormat:@</code><code>"Code%ld.jpg"</code><code>,(</code><code>long</code><code>)i];</code>
<code> </code><code>UIImage *image=[UIImage imageNamed:imageName];</code>
<code> </code><code>book.ConverPicture=image;</code>
<code> </code><code>book.BookName=[</code><code>NSString</code> <code>stringWithFormat:@</code><code>"百年孤獨%ld"</code><code>,(</code><code>long</code><code>)i];</code>
<code> </code><code>book.Author=[</code><code>NSString</code> <code>stringWithFormat:@</code><code>"加西亞.馬爾克斯%ld"</code><code>,(</code><code>long</code><code>)i];</code>
<code> </code><code>book.Price=[[</code><code>NSNumber</code> <code>alloc] initWithInteger:45];</code>
<code> </code><code>[</code><code>self</code><code>.bookList addObject:book];</code>
<code> </code>
<code> </code><code>}</code>
<code> </code><code>if</code> <code>([</code><code>NSKeyedArchiver</code> <code>archiveRootObject:</code><code>self</code><code>.bookList toFile:_storageListPath]) {</code>
<code> </code><code>NSLog</code><code>(@</code><code>"資料存檔成功"</code><code>);</code>
多個解檔:
<code>self</code><code>.bookList=[</code><code>NSKeyedUnarchiver</code> <code>unarchiveObjectWithFile:_storageListPath];</code>
<code>Book *nextBook=</code><code>self</code><code>.bookList[1];</code>
<code>self</code><code>.myImageView.image=nextBook.ConverPicture;</code>
<code>NSLog</code><code>(@</code><code>"解檔成功"</code><code>);</code>
通過代碼基本上發現其實存檔和解壓是非常簡單的一個事情,不過事實這種方式缺點還是很明顯的,以這種方式儲存資料隻能一次性歸檔儲存以及一次性解壓。資料較少的時候如果使用感覺比較友善,資料量過多的時候如果想修改其中的某一條,解壓整個資料然後歸檔整個資料還是比較耗時的。最終示範效果如下:
本文轉自Fly_Elephant部落格園部落格,原文連結:http://www.cnblogs.com/xiaofeixiang/p/4266156.html,如需轉載請自行聯系原作者