iOS--歸檔和解檔(Archiver)、(UnArchiver)

来源:http://www.cnblogs.com/bolin-123/archive/2016/03/21/5303481.html
-Advertisement-
Play Games

一、已有類型的歸檔和解檔 首先來看一個簡單的例子: //第二種方式 //第一種方式的缺陷是一個對象歸檔成一個文件 //但是第二種方式,多個對象可以歸檔成一個文件 NSArray *array = [NSArray arrayWithObjects:@"zhangsan",@"lisi", nil];


一、已有類型的歸檔和解檔

首先來看一個簡單的例子:

 //第一方式:歸檔對象
    //對象-->文件
     NSArray *array = [NSArray arrayWithObjects:@"zhang",@"wangwu",@"lisi",nil];
   
    // NSHomeDirectory 獲取根目錄 stringByAppendingPathComponent 添加儲存的文件名
    
     NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
     BOOL success = [NSKeyedArchiver archiveRootObject:array toFile:filePath];
     if(success){
         NSLog(@"保存成功");
     }else {
         NSLog(@"未保存");
     }
   //  解歸檔
     array = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
     NSLog(@"%@",array);

 //第二種方式

    //第一種方式的缺陷是一個對象歸檔成一個文件

    //但是第二種方式,多個對象可以歸檔成一個文件

     NSArray *array = [NSArray arrayWithObjects:@"zhangsan",@"lisi", nil];

     NSMutableData *data = [NSMutableData data];

     NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

     //編碼

     [archiver encodeObject:array forKey:@"array"];

     [archiver encodeInt:100 forKey:@"scope"];

     [archiver encodeObject:@"jack" forKey:@"name"];

     //完成編碼,將上面的歸檔數據填充到data中,此時data中已經存儲了歸檔對象的數據

     [archiver finishEncoding];

     NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];

     BOOL success = [data writeToFile:filePath atomically:YES];

     if(success){

     NSLog(@"歸檔成功");

     }

 

    //  對多個對象進行解檔操作

    /*

    NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];

    //讀取歸檔數據

    NSData *data = [[NSData alloc] initWithContentsOfFile:filePath];

    

    //創建解歸檔對象,對data中的數據進行解歸檔

    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];

    

    //解歸檔

    NSArray *array = [unarchiver decodeObjectForKey:@"array"];

    NSLog(@"%@",array);

    

    int value = (int)[unarchiver decodeObjectForKey:@"scope"];

    NSLog(@"%d",value);

     */

  • 歸檔  下麵這段代碼是將一個NSArray對象寫入到一個文件中。
//對象-->文件
     NSArray *array = [NSArray arrayWithObjects:@"zhang",@"wangwu",@"lisi",nil];
   
    // NSHomeDirectory 獲取根目錄 stringByAppendingPathComponent 添加儲存的文件名
    
     NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
     BOOL success = [NSKeyedArchiver archiveRootObject:array toFile:filePath];
     if(success){
         NSLog(@"保存成功");
     }else {
         NSLog(@"未保存");

下麵代碼是創建一個文件的方法

NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
  • 解檔  下麵代碼是解檔就是返回一個對象
array = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
     NSLog(@"%@",array);
  • 對多個對象進行歸檔到一個文件
//第二種方式
    //第一種方式的缺陷是一個對象歸檔成一個文件
    //但是第二種方式,多個對象可以歸檔成一個文件
     NSArray *array = [NSArray arrayWithObjects:@"zhangsan",@"lisi", nil];
     NSMutableData *data = [NSMutableData data];
     NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
     //編碼
     [archiver encodeObject:array forKey:@"array"];
     [archiver encodeInt:100 forKey:@"scope"];
     [archiver encodeObject:@"jack" forKey:@"name"];
     
     //完成編碼,將上面的歸檔數據填充到data中,此時data中已經存儲了歸檔對象的數據
     [archiver finishEncoding];
     
     NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
     BOOL success = [data writeToFile:filePath atomically:YES];
     if(success){
     NSLog(@"歸檔成功");
     }

多個對象歸檔的話,這裡要用到一個類:NSMutableDataNSData,他們兩的區別很簡單,一個是可變的,一個是不可變的。然後這裡還創建了一個歸檔器:NSKeyedArchiver,這個類負責進行指定類型的編碼操作,然後將數據填充到NSMutableData類。歸檔的時候對每個類型對象用一個key進行對應,這個NSDataNSDirctionary很類似了。

  • 對多個對象進行解檔操作
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
    //讀取歸檔數據
    NSData *data = [[NSData alloc] initWithContentsOfFile:filePath];
    
    //創建解歸檔對象,對data中的數據進行解歸檔
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    
    //解歸檔
    NSArray *array = [unarchiver decodeObjectForKey:@"array"];
    NSLog(@"%@",array);
    
    int value = (int)[unarchiver decodeObjectForKey:@"scope"];
    NSLog(@"%d",value);

我們可以將文件解檔出一個NSData對象,然後可以通過key去獲取指定的類型對象

 

二、自定義類型的歸檔和解檔

上面說到了已有類型的歸檔和解檔,下麵來看一下自定義類型的歸檔和解檔操作,在開始的時候也說了,如果自定義的類型可以進行歸檔和解檔的話,必須實現一個協議:NSCoding

Student.h

 

#import <Foundation/Foundation.h>

// 類只有實現NSCoding協議才能歸檔
@interface Student : NSObject<NSCoding>

@property(copy,nonatomic)NSString *name;
@property(assign,nonatomic)int age;
@property(strong,nonatomic) NSString *adder;

@end

這裡自定義了一個Student類型,實現了NSCoding協議,然後他有三個屬性,這裡我們看到有新的方法去定義屬性

Student.m

#import "Student.h"

@implementation Student

// 歸檔時調用   也是一個初始化

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    NSLog(@"initWithCoder");
    self = [super init];
    if (self!=nil) {
         //一般我們將key定義成巨集,這樣就不會出錯
        _name = [[aDecoder decodeObjectForKey:@"name"] copy];
        self.age = (int)[aDecoder decodeIntegerForKey:@"age"];
        _adder=[aDecoder decodeObjectForKey:@"adder"];
    }
    return self;
}

// 歸檔時調用此方法
- (void)encodeWithCoder:(NSCoder *)aCoder{
    NSLog(@"encodeWithCoder");
    [aCoder encodeObject:_name forKey:@"name"];//一般key和屬性名是取一樣的
    [aCoder encodeInteger:_age forKey:@"age"];
    [aCoder encodeObject:_adder forKey:@"adder"];
    
}

// 描述方法
- (NSString *)description
{
    return [NSString stringWithFormat:@"name=%@,age=%d,adder=%@", _name,_age,_adder];
}

@end

在Person.m文件中,我們需要實現協議中的兩個方法:

initWithCoder

encodeWithCoder

這兩個方法一個是用於歸檔操作時會調用的方法,還有一個是用於解檔操作時會調用的方法

1、解檔的時候用到的方法

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    NSLog(@"initWithCoder");
    self = [super init];
    if (self!=nil) {
         //一般我們將key定義成巨集,這樣就不會出錯
        _name = [[aDecoder decodeObjectForKey:@"name"] copy];
        self.age = (int)[aDecoder decodeIntegerForKey:@"age"];
        _adder=[aDecoder decodeObjectForKey:@"adder"];
    }
    return self;
}

這個是一個初始化的方法,同時他也是一個解檔操作時會調用的方法,所以在這裡我們既要寫一下初始化方法的特定代碼,還要寫上解檔的代碼,這裡主要看解檔的代碼

其實很簡單,就是對屬性重新寫一下值,然後對每個屬性指定一個key就可以了。

 

2、歸檔的時候用到的方法

// 歸檔時調用此方法
- (void)encodeWithCoder:(NSCoder *)aCoder{
    NSLog(@"encodeWithCoder");
    [aCoder encodeObject:_name forKey:@"name"];//一般key和屬性名是取一樣的
    [aCoder encodeInteger:_age forKey:@"age"];
    [aCoder encodeObject:_adder forKey:@"adder"];
    
}

歸檔和解檔的操作正好相反的,但是要註意的是:他們屬性的key一定要保持一致

 3、重寫description方法

- (NSString *)description
{
    return [NSString stringWithFormat:@"name=%@,age=%d,adder=%@", _name,_age,_adder];
}

在之前的文章中我說道過,我們在使用NSLog方法列印對象的值的時候,其實是調用對象的description方法,而這個方法是NSObject類中的,我們可以重寫他,這樣我們就可以列印我們想要的信息了。和Java中的toString方法一樣。

 

下麵就來看一下使用方法了

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    Student *stu=[Student new];
    stu.name=@"張三";
    stu.age=12;
    stu.adder=@"北京";
    
    // 歸檔
    NSString *filePath=[NSHomeDirectory() stringByAppendingPathComponent:@"message.plist"];
    NSLog(@"%@",filePath);
    BOOL bol=[NSKeyedArchiver archiveRootObject:stu toFile:filePath];
    
    if (bol) {
        NSLog(@"歸檔成功");
    }else{
        NSLog(@"歸檔成功");
    }

    // 解歸檔
    Student *stu1=[NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    NSLog(@"%@",stu1);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

我們可以看到,使用起來是很簡單的和上面的方式一樣,運行結果:

看到了,我們自定義的description方法,列印了我們自己想要的結果~~

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先,React.js是facebook在2013年5月開源的一個前端框架,React不是一個MVC框架,它是構建易於可重覆調用的web組件,側重於UI, 也就是view層, React為了更高超的性能而使用虛擬DOM作為其不同的實現。 它同時也可以由服務端Node.js渲染 - 而不需要過重的瀏覽
  • 最近做重構,有一個功能是,滑鼠點擊鏈接後顯示不同樣式: 代碼如下,樣式佈局我修改後如下,使用bootstrap框架來做。 現在重點說一下:功能實現。 原來代碼是這樣實現鏈接點擊樣式的,給每個鏈接不同的class, 然後在page1.html頁面定義: 同理在page2.html頁面定義: 在page
  • Firebug功能異常強大,不僅可以調試DOM,CSS,還可以調試JS代碼,下麵介紹一下調試JS。 console對象是Firebug內置的對象,該對象可以在代碼中寫入,可以在控制面板中寫入。 1)有五個方法來顯示信息。依次為: 1、console.log(),可以用來取代alert()或docum
  • 之前計劃是一周還原一個網頁或者切一張psd來練習基本功的。正好周五的時候接到一個電話面試,讓我還原一下163郵箱主頁,晚上發給他,就正好當是這周的練習吧。 吃完晚飯開工,做到12點,差不多4個小時,基本上做完了,不過還有些局部沒完成。算還原度90%吧,剩下的這兩天有空再補啦。 這是目前的完成情況 w
  • 最近在學習NodeJS,用到了express,看著官網上的API手冊,打算把其中比較常用到的API根據自己理解翻譯一下,方便自己學習使用. 該篇打算用來記錄下express中res. 由於水平有限,希望能得到大家的修改,在學習過程中我會持續更新修改 Response res對象表示的是Express
  • 常用正則表達式大全!(例如:匹配中文、匹配html) 匹配中文字元的正則表達式: [u4e00-u9fa5] 評註:匹配中文還真是個頭疼的事,有了這個表達式就好辦了 匹配雙位元組字元(包括漢字在內):[^x00-xff] 評註:可以用來計算字元串的長度(一個雙位元組字元長度計2,ASCII字元計1) 匹
  • web前端開發-編寫高性能JavaScript 很多JavaScript引擎,如Google的V8引擎(被Chrome和Node所用),是專門為需要快速執行的大型JavaScript應用所設計的。如果你是一個開發者,並且關心記憶體使用情況與頁面性能,你應該瞭解用戶瀏覽器中的JavaScript引擎是如
  • 之前本來打算在寫兩個篇幅,但是在這片開寫的時候覺得還是寫一個比較好,有利於理解。NSURLSession下載是通過NSURLSession下載代理實現的,上一片也介紹了代理,之所以沒有介紹下載是因為,我個人覺得容易混淆(應該是我太笨)。這篇隨筆里將會介紹NSURLSession下載的實現,包括下載的
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...