iOS開發-數據存儲NSCoder


軟件中永遠繞不開的一個問題就是數據存儲的問題,PC的時候一般都是選擇在數據庫中存儲,iOS如果是和后端配合的話,那么不需要考慮數據存儲的這個問題,上次寫了一下plist的存儲,不過數據都是存儲一些簡單的鍵值對對象。本次需要將一些自己定義的類型存儲在plist比如說圖片,這個時候可以利用NSCoding協議,將數據地以類似檔案的形式存儲到plist文件中,然后從plist的文件中讀取數據,使用協議的時候這個時候就會用到了NSCoder,如果對存檔和解壓沒有概念的話,可以簡單的理解為數據的序列化與反序列化。

基礎概念

NSCoding是一個protocol. 如果實現了NSCoding,需要實現其中的兩個方法:

- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder; // NS_DESIGNATED_INITIALIZER

 方法中的主要的參數就是NSCoder,它是archivie字節流的抽象類.可以將數據寫入一個coder,也可以從coder中讀取我們寫入的數據. NSCoder是一個抽象類,不能直接使用它來創建對象. 但是可以通過其子類NSKeyedUnarchiver從字節流中讀取數據,NSKeyedArchiver將對象寫入到字節流。本文以書籍為例:

新建一個Book類,Book.h中的代碼:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface Book : NSObject<NSCoding>

@property (strong,nonatomic) UIImage *ConverPicture;

@property (strong,nonatomic) NSString *BookName;

@property (strong,nonatomic) NSString *Author;

@property (strong,nonatomic) NSNumber *Price;

@end

Book.m中實現NSCoding的兩個方法,注意中UIImage的寫法與其他有所不同:

@implementation Book

- (void)encodeWithCoder:(NSCoder *)aCoder{
    
    //注意這里是存儲的是JPG圖片的調用
    [aCoder encodeObject:UIImageJPEGRepresentation(self.ConverPicture,1.0)forKey:@"ConverPicture"];
    [aCoder encodeObject:_BookName forKey:@"BookName"];
    [aCoder encodeObject:_Author forKey:@"Author"];
    [aCoder encodeObject:_Price forKey:@"Price"];
    
}

- (id)initWithCoder:(NSCoder *)aDecoder{
    
    self.ConverPicture=[UIImage imageWithData:[aDecoder decodeObjectForKey:@"ConverPicture"]];
    self.BookName=[aDecoder decodeObjectForKey:@"BookName"];
    self.Author=[aDecoder decodeObjectForKey:@"Author"];
    self.Price=[aDecoder decodeObjectForKey:@"Price"];
    return self;
    
}
@end

Demo實現

正常的情況的不需要新建頁面的,不過需要演示一下UIImage的效果,Main.storyboard中的布局:

稍微解釋一下,前兩個是存的單文件,后兩個存的是多文件,UIImage展示存儲的圖片:

ViewController定義字段:

@property (strong,nonatomic) NSString *storagePath;

@property (strong,nonatomic) NSString *storageListPath;

@property (strong,nonatomic) NSMutableArray *bookList;

設置路徑,如果不是很清晰,可參考本文之前的博客:

  NSArray *codepath= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    _storagePath = [codepath[0] stringByAppendingPathComponent:@"book.plist"];
        NSLog(@"%@",NSHomeDirectory());
    _storageListPath = [codepath[0] stringByAppendingPathComponent:@"booklist.plist"];

 單個存檔:

 Book *book=[[Book alloc]init];
    UIImage *image=[UIImage imageNamed:@"Code1.jpg"];
    book.ConverPicture=image;
    book.BookName=@"百年孤獨";
    book.Author=@"加西亞.馬爾克斯";
    book.Price=[[NSNumber alloc] initWithInteger:45];
    if ([NSKeyedArchiver archiveRootObject:book toFile:_storagePath]) {
        NSLog(@"數據存檔成功");
    }

 單個解壓:

  Book *decodeBook=[NSKeyedUnarchiver unarchiveObjectWithFile:_storagePath];
    self.myImageView.image=decodeBook.ConverPicture;
       NSLog(@"%@",decodeBook.ConverPicture);
    NSLog(@"%@",decodeBook.BookName);
    NSLog(@"解檔成功");

 多個存檔:

  self.bookList=[NSMutableArray array];
    for (NSInteger i=1; i<3; i++) {
        Book *book=[[Book alloc]init];
        NSString *imageName=[NSString stringWithFormat:@"Code%ld.jpg",(long)i];
        UIImage *image=[UIImage imageNamed:imageName];
        book.ConverPicture=image;
        book.BookName=[NSString stringWithFormat:@"百年孤獨%ld",(long)i];
        book.Author=[NSString stringWithFormat:@"加西亞.馬爾克斯%ld",(long)i];
        book.Price=[[NSNumber alloc] initWithInteger:45];
        [self.bookList addObject:book];
    
    }
    if ([NSKeyedArchiver archiveRootObject:self.bookList toFile:_storageListPath]) {
        NSLog(@"數據存檔成功");
    }

 多個解檔:

    self.bookList=[NSKeyedUnarchiver unarchiveObjectWithFile:_storageListPath];
    Book *nextBook=self.bookList[1];
    self.myImageView.image=nextBook.ConverPicture;
    NSLog(@"解檔成功");

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

參考資料:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Articles/creating.html#//apple_ref/doc/uid/20000949-BABGBHCA


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM