天天看點

iOS開發-資料存儲NSCoder

軟體中永遠繞不開的一個問題就是資料存儲的問題,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 &lt;Foundation/Foundation.h&gt;</code>

<code>#import &lt;UIKit/UIKit.h&gt;</code>

<code>@interface</code> <code>Book : </code><code>NSObject</code><code>&lt;</code><code>NSCoding</code><code>&gt;</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中的布局:

iOS開發-資料存儲NSCoder

稍微解釋一下,前兩個是存的單檔案,後兩個存的是多檔案,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&lt;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>

 通過代碼基本上發現其實存檔和解壓是非常簡單的一個事情,不過事實這種方式缺點還是很明顯的,以這種方式儲存資料隻能一次性歸檔儲存以及一次性解壓。資料較少的時候如果使用感覺比較友善,資料量過多的時候如果想修改其中的某一條,解壓整個資料然後歸檔整個資料還是比較耗時的。最終示範效果如下:

iOS開發-資料存儲NSCoder

本文轉自Fly_Elephant部落格園部落格,原文連結:http://www.cnblogs.com/xiaofeixiang/p/4266156.html,如需轉載請自行聯系原作者