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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...