1. 程式人生 > >iOS資料持久化儲存:歸檔

iOS資料持久化儲存:歸檔

在平時的iOS開發中,我們經常用到的資料持久化儲存方式大概主要有:NSUserDefaults(plist),檔案,資料庫,歸檔。。前三種比較經常用到,第四種歸檔我個人感覺用的還是比較少的,恰恰因為用的比較少,但是還是有地方要用到,所以今天再把歸檔解檔複習一遍吧。

一、什麼是歸檔:

  物件歸檔是將物件以檔案的形式儲存到磁碟中(也稱為序列化,持久化) ;使用的時候讀取該檔案的儲存路徑讀取檔案的內容(也稱為解檔,反序列化)

二、歸檔 與 plist儲存的區別:

  • 物件歸檔的檔案是保密的,在磁碟上無法檢視檔案中的內容,而plist屬性列表是明文的可以檢視。
  • 其次就是儲存的資料型別不同
    • 只要是物件型別,歸檔都可以儲存。
    • 而plist只能儲存這幾種型別:NSString  NSNumber  NSDate NSData NSArray NSDictionary  。不能儲存其他的型別

三、歸檔的使用

  剛剛說到,只要是物件型別,都可以用歸檔的方式進行儲存。

  但是,只有實現了<NSCoding>協議的型別才可以進行歸檔,由於Foudation框架中的物件型別已經實現了NSCoding協議,所以可以直接歸檔解檔,而我們自定義的型別,則需要我們手動去實現NSCoding協議。必須實現一下兩個方法:

//歸檔的時候呼叫的方法
- (void)encodeWithCoder:(NSCoder *)aCoder; //解歸檔的時候要呼叫的函式 - (id)initWithCoder:(NSCoder *)aDecoder;

  1.對系統類的歸檔:

    第一種方式:單個物件的歸檔和解檔

//單個物件歸檔:
    NSArray *array1 = @[@"zhangsan",@"wangwu",@"lisi"];
    NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
    BOOL success 
= [NSKeyedArchiver archiveRootObject:array1 toFile:filePath]; if (success) { NSLog(@"儲存成功!"); } //單個物件解檔 id array2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; NSLog(@"%@",array2);

    第二種方式:多個物件的歸檔和解檔

    //多個物件歸檔:
    NSArray *array1 = @[@"zhangsan",@"wangwu",@"lisi"];
    NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    //編碼
    [archiver encodeObject:array1 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(@"歸檔成功");
    }
    
    //多個物件解檔
    NSData *data2 = [[NSData alloc] initWithContentsOfFile:filePath];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data2];
    NSArray *array = [unarchiver decodeObjectForKey:@"array"];
    NSLog(@"%@",array);
    int value = [unarchiver decodeIntForKey:@"scope"];
    NSLog(@"%d",value);
  [unarchiver finishDecoding];


  2.自定義型別的歸檔解檔

  上面已經說過了,對系統型別可以直接進行歸檔和解檔,但是對於自定義型別,必須實現NSCoding協議

#import <Foundation/Foundation.h>
#import "Car.h"

int main(int argc, const char * argv[])
{
    /*
     有輛汽車 有一個引擎 和 四個輪胎
     
     然後需要對這個汽車進行歸檔 本地儲存資料
     這時 還必須要對汽車的引擎和輪胎也要歸檔
     
     只要有成員變數是物件地址 都要繼續歸檔 
     
     那麼這時歸檔的類 都要遵守協議NSCoding 實現裡面的方法
     
     實際上 歸檔就是一個深拷貝
     */
    
    @autoreleasepool {
     
#if 0
        Car *BMW = [[Car alloc] init];
        BMW.speed = 100;
        [BMW run];
        
        //程式結束之前把汽車物件的資訊進行儲存到本地
        //歸檔
        
        NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"car.src"];
        
        BOOL ret = [NSKeyedArchiver archiveRootObject:BMW toFile:filePath];
        if (ret) {
            NSLog(@"汽車物件歸檔成功");
        }else {
            NSLog(@"汽車歸檔失敗");
        }
        [BMW release];
        
#else
        //解歸檔-->從檔案中獲取資料建立一個Car物件
        
        NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"car.src"];

        Car *car = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
        
        NSLog(@"car.speed:%ld",car.speed);
        NSLog(@"engine.name:%@",car.engine.name);
        [car run];
    
#endif
        
    }
    return 0;
}

  汽車類:

#import <Foundation/Foundation.h>
#import "Engine.h"
#import "Tyre.h"

//遵守歸檔協議
@interface Car : NSObject<NSCoding>
{
    Engine *_engine;
    NSMutableArray *_tyresArr;
    NSInteger _speed;
}
@property (nonatomic) NSInteger speed;
@property (nonatomic,retain) Engine *engine;
- (Car *)init;
- (void)run;
@end
#import "Car.h"

@implementation Car
- (void)dealloc {
    NSLog(@"汽車銷燬");
    [_engine release];
    [_tyresArr release];
    [super dealloc];
}

//對Car歸檔的時候會呼叫的方法
- (void)encodeWithCoder:(NSCoder *)aCoder {
    //就是對成員變數的資料進行歸檔
    //如果成員變數是基本型別 那麼直接歸檔
    //如果成員變數變數是物件地址 那麼物件的類也要遵守協議實現方法
    
    //在類中 如果有setter和getter方法那麼儘量使用setter和getter方法
    [aCoder encodeInteger:self.speed forKey:@"speed"];
    //對一個物件地址指向的物件進行歸檔 那麼指向物件也要實現歸檔協議的方法 Engine 要遵守 陣列要遵守 陣列的元素也要遵守
    [aCoder encodeObject:self.engine forKey:@"engine"];
    [aCoder encodeObject:_tyresArr forKey:@"array"];
}
//物件解歸檔、讀檔的時候呼叫
- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {//如果父類有initWithCoder那麼呼叫父類的initWithCoder:
        
        //這裡不要直接寫 成員變數 否則就有可能崩潰
        //要用setter方法 這樣 內部會計數器+1 擁有絕對使用權
        //讀檔
        self.engine = [aDecoder decodeObjectForKey:@"engine"];
        NSLog(@"%ld",self.engine.retainCount);
        self.speed = [aDecoder decodeIntegerForKey:@"speed"];
        //要注意擁有絕對使用權
        _tyresArr = [[aDecoder decodeObjectForKey:@"array"] retain];
        
    }
    return self;
}



- (Car *)init {
    if (self = [super init]) {
        _engine = [[Engine alloc] init];
        _engine.name = @"德國";
        _engine.power = 1000;
        
        _tyresArr = [[NSMutableArray alloc] init];
        for (int i = 0; i < 4; i++) {
            Tyre *tyre = [[Tyre alloc] init];
            tyre.name = @"米其林";
            tyre.type = 12345;
            [_tyresArr addObject:tyre];
            [tyre release];
        }
    }
    return self;
}
- (void)run {
    NSLog(@"汽車跑");
    [self.engine start];
    for (Tyre *tyre in _tyresArr) {
        [tyre scroll];//滾動
    }
}

@end

輪胎類:

#import <Foundation/Foundation.h>

@interface Tyre : NSObject<NSCoding>
{
    NSString *_name;
    NSInteger _type;
}
@property (nonatomic,copy)NSString *name;
@property (nonatomic)NSInteger type;
- (void)scroll;

@end
#import "Tyre.h"

@implementation Tyre
- (void)dealloc {
    NSLog(@"輪胎銷燬");
    self.name = nil;
    [super dealloc];
}
//歸檔呼叫
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInteger:self.type forKey:@"type"];
}
//讀檔呼叫
- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        //用setter方賦值 內部有計數器+1 
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.type = [aDecoder decodeIntegerForKey: @"type"];
    }
    return self;
}


- (void)scroll {
    NSLog(@"%@ 輪胎在滾動",self.name);
}
@end

引擎類:

#import <Foundation/Foundation.h>

@interface Engine : NSObject <NSCoding>
{
    NSString *_name;
    NSInteger _power;
}
@property (nonatomic,copy)NSString *name;
@property (nonatomic) NSInteger power;
- (void)start;
@end
#import "Engine.h"

@implementation Engine
- (void)dealloc {
    NSLog(@"引擎銷燬");
    self.name = nil;
    [super dealloc];
}
//歸檔呼叫
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInteger:self.power forKey:@"power"];
}
//讀檔呼叫
- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.power = [aDecoder decodeIntegerForKey: @"power"];
    }
    return self;
}

- (void)start {
    NSLog(@"引擎啟動");
}
@end

相關推薦

iOS資料持久化儲存:歸檔

在平時的iOS開發中,我們經常用到的資料持久化儲存方式大概主要有:NSUserDefaults(plist),檔案,資料庫,歸檔。。前三種比較經常用到,第四種歸檔我個人感覺用的還是比較少的,恰恰因為用的比較少,但是還是有地方要用到,所以今天再把歸檔解檔複習一遍吧。 一、什麼是歸檔:   物件歸檔是將物件以

ios 資料持久化儲存

說到資料儲存,我們不得不先了解下蘋果的沙盒 、如何獲取沙盒路徑和沙盒目錄下對應的檔案: 一、沙盒(sandbox) 每一個App都有一個儲存空間。iOS系統為每個應用程式建立自己的目錄,每個應用程式只能訪問自己的目錄,不能相互通訊。 沙盒主要包括下面幾個檔案:用模擬器執行 NS

iOS開發——CoreData資料持久化儲存

coreData是用於對資料進行例項化處理的類 首先在建立專案的時候需要勾選Use Core Data 在勾選了coreData之後會生成對應的.xcdatamodeld檔案。 這種檔案在經過編譯之後會變成 .momd檔案 然後選中這個檔案 雙擊開啟 點選下面的加號

iOS 資料儲存和讀取之歸檔

歸檔四一種很常見的檔案儲存方法,幾乎任何型別的物件都能夠被歸檔儲存(實際上是一種檔案儲存形式)。 使用NSKeyedArichiver進行歸檔,用NSKeyedUnarichiver進行解歸檔。這種方式會在寫入、讀出資料之前堆資料進行序列化、反序列化操作。 一,簡單歸檔 

iOS 資料持久化之使用NSUserDefaults儲存資料

iOS下可以使用NSUserDefaults、sqlite、CoreData幾種常用的方式來儲存資料,其中NSUserDefaults用來儲存類似使用者的配置等這些的資料,後兩者使用者儲存大批量和比較複雜的資料。NSUserDefault的使用比較簡單: NSUserDef

iOS 數據儲存--歸檔

sea 。。 property append direct mobile mas rect bsp 四種數據持久化方式 http://www.cocoachina.com/ios/20160617/16739.html //先把數據在model中歸解檔 。h @pro

iOS持久化儲存 plist、NSUserDefaults、NSKeyedArchiver、資料庫

1.什麼是持久化? 本人找了好多文章都沒有找到滿意的答案,最後是從孫衛琴寫的《精通Hibernate:Java物件持久化技術詳解》中,看到如下的解釋,感覺還是比較完整的。摘抄如下:  狹義的理解: “持久化”僅僅指把域物件永久儲存到資料庫中;廣義的理解,“持久化”包括和資料庫相關的各種操作。&n

iOS-資料持久化之Sqllite

iOS中的資料儲存方式 Plist(NSArray\NSDictionary) Preference(偏好設定\NSUserDefaults) NSCoding(NSKeyedArchiver\NSkeyedUnarchiver) SQLite3 Core Data

[Xcode10 實際操作]七、檔案與資料-(11)資料持久化儲存框架CoreData的使用:建立CoreData實體並插入資料

本文將演示【CoreData】資料持久化儲存框架的使用。 點選【Create a new Xcode project】建立一個新的專案 ->【Single View App】選擇建立一個簡單的單檢視應用->【Next】 【Product Name】:CoreDataProject 勾選使用

[Xcode10 實際操作]七、檔案與資料-(12)資料持久化儲存框架CoreData的使用:查詢CoreData中的資料

本文將演示如何查詢資料持久化物件。 在專案導航區,開啟檢視控制器的程式碼檔案【ViewController.swift】 1 import UIKit 2 //引入資料持久化儲存框架【CoreData】 3 import CoreData 4 5 class ViewContro

python 基礎之資料持久化儲存

###資料持久化儲存 - 說明:持久化儲存方案,普通檔案、資料庫、序列化 - 示例: ```python import pickle class Person: def __init__(self, name, age): self.name = na

iOS 資料持久化 CoreData的版本遷移

一般程式app升級時,資料庫有可能發生改變,如增加表字段,增加表等。 此時有兩種操作: 第一種就是毫無留情的把本地舊資料庫直接刪掉,重新建立新的資料庫; 第二種就是資料庫遷移,更新資料庫。 第一種情況是簡單粗暴型,但不會保留任何歷史資料,一般不推薦使用。 這裡主要介紹第二

iOS 資料持久化 CoreData

            CoreData是iOS3.0後引入的資料持久化解決方案, 是一種物件關係對映(ORM), 例如java後臺中的Hibernate, iOS中ORM框架首先CoreDat

eos原始碼賞析(十三):EOS智慧合約資料持久化儲存(上)

前面的文章(eos原始碼賞析(十):EOS智慧合約入門之區塊上鍊)中提到了fork_db,區塊生產之後會將區塊的狀態資訊等儲存在fork_db中,但是當這個動作完成之後,fork_db中的內容就會變化,用來儲存下一個區塊的狀態資訊,並不能實現對歷史區塊資訊的儲存。對於區塊鏈來

iOS 資料持久化方式

所謂歸檔:將複雜物件轉化為NSData型別資料(複雜-->歸檔-->NSData--->WriteToFile)注意:歸檔是將物件轉化為資料位元組,以檔案的形式儲存在磁碟上, 所謂反歸檔:將NSData型別資料轉化為複雜物件(讀取檔案-->NSDat

OC-NSUserDefaults(簡單資料持久化儲存機制)

//將值放到一箇中間位置,任何物件都可以訪問該位置(單例,資料庫,檔案系統) // NSUserDefaults:使用者預設設定,可以作為簡單資料的持久化儲存機制,基於檔案系統(就是一直存在的) //NSUserDefa

餓了麼開源專案:便捷高效的Android資料持久化儲存框架

版權所有。所有權利保留。 歡迎轉載,轉載時請註明出處: Android應用開發時經常要對許多資料進行持久化儲存,便於以後訪問。 對於int、double、boolean這些基本資料,可以使用SharedPreference。對於一些物件,往SharedPrefe

iOS資料持久化的應用場景

iOS 開發中,一般有如下幾種資料儲存方式。需要根據具體的業務場景,選擇 合適的資料儲存方式。1.(1) 使用者預設設定 – 這種情況通常不需要使用者干預,如遊戲通關資訊,Video播放記錄,或者 App 退出之後,下次進入時,希望恢復到退出時的情況。2.(2) 設定束(S

prometheus基於influxdb的監控資料持久化儲存方案

用prometheus在線上跑了兩年了,都是用的本地磁碟做資料儲存,磁碟空間有限,當空間不足時直接刪除資料檔案。近期監控系統正式上

iOS資料儲存持久化(plist,偏好設定,歸檔

1,plist 使用plist儲存資料,首先要指定路徑(一般在Document路徑下),plist只支援以下的型別: NSArray; NSMutableArray; NSDictionary; NSMutableDictionary; NSData; NSMutableD