解放雙手,Swift和OC,一句話歸檔解檔的BaseModel

請看具體實現(xiàn),注釋詳細. 覺得用的上的朋友麻煩點個贊.自己寫的實用小工具.
使用的時候直接繼承自BaseModel 就可以了

    //字典轉(zhuǎn)模型
    let model = BaseModel.init(dict: dic)
    
    //一句話快速歸檔,括號內(nèi)輸入單個模型或者模型數(shù)組
    model.archiverWithRootObject([model1, model2, model3])

    //一句話快速解檔.無論你存入的是單個對象還是數(shù)組
    let modelArray = account.unarchiver()
一句話歸檔效果,數(shù)據(jù)是本人的微博信息.

怎么樣?是不是非常的cool,以下是兩個語言版本的具體實現(xiàn),希望用的同時能認真看注釋,理解其中簡單的原理.

OC版本

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@implementation BaseModel

- (instancetype)initWithDic:(NSDictionary *)dic
{
    if (self = [super init]) {
        [self setValuesForKeysWithDictionary:dic];
    }    
    return self;
}

#pragma mark 數(shù)據(jù)持久化
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    //獲取當前類的所有屬性名稱
    unsigned int outCount, i;
    objc_property_t *properties =class_copyPropertyList([self class], &outCount);
    
    //遍歷所有的屬性名稱
    for (i = 0; i < outCount; i++)
    {
        //取出單個屬性名稱
        objc_property_t property = properties[i];
        const char* char_f = property_getName(property);
        //轉(zhuǎn)換成OC串
        NSString *propertyName = [NSString stringWithUTF8String:char_f];
        //KVC取值
        id propertyValue = [self valueForKey:(NSString *)propertyName];
        //如果取出來有值 則歸檔
        if (propertyValue)
        {
            [aCoder encodeObject:propertyValue forKey:propertyName];
        }
    }
}



- (id)initWithCoder:(NSCoder *)aCoder
{
    self = [super init];
    if (self)
    {
        //取出所有的屬性名稱
        unsigned int outCount, i;
        objc_property_t *properties =class_copyPropertyList([self class], &outCount);
        
        //遍歷屬性
        for (i = 0; i<outCount; i++)
        {
            //取出單個屬性
            objc_property_t property = properties[i];
            const char* char_f = property_getName(property);
            NSString *propertyName = [NSString stringWithUTF8String:char_f];
            
            //KVC賦值
            [self setValue:[aCoder decodeObjectForKey:propertyName] forKey:propertyName];

        }
    }
    return self;
}

//存檔
+ (void)archiverWithRootObject:(id)rootObject{
    
    NSString *fileName = NSStringFromClass([self class]);
    
    [NSKeyedArchiver archiveRootObject:rootObject toFile:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:fileName]];
}

//解檔
+ (id)unarchiver{
    NSString *fileName = NSStringFromClass([self class]);
    return [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:fileName]];
}
@end

Swift版本


//
//  BaseModel.swift
//  WeiboSwift
//
//  Created by 曾凡怡 on 2017/1/5.
//  Copyright ? 2017年 曾凡怡. All rights reserved.
//

import UIKit
class BaseModel: NSObject,NSCoding {
    
    
    init(dict : [String : Any]) {
        super.init()
        setValuesForKeys(dict)
    }
    
    required init?(coder aDecoder: NSCoder) {
        //先初始化
        super.init()
        //獲取當前類的所有屬性名
        let nameList = getPropertyNameList()
        //進行解檔
        for key in nameList{
            //從aDecoder中取值
            let value = aDecoder.decodeObject(forKey: key)
            //賦值給自己
            setValue(value, forKey: key)
        }
    }
    
    func encode(with aCoder: NSCoder) {
        //獲取當前類的所有屬性名
        let nameList = getPropertyNameList()
        //進行歸檔
        for key in nameList{
            //KVC取值
            if let value = value(forKey: key){
                ////歸檔.此處注意歸檔的方法中要使用帶 forKey參數(shù)的
                aCoder.encode(value, forKey: key)
            }
        }
    }
    
    func getPropertyNameList () -> [String]{
        //保存屬性的個數(shù)
        var outCount : UInt32 = 0
        //保存屬性名稱的數(shù)組
        var list : [String] = []
        
        //獲取屬性集合
        let property = class_copyPropertyList(type(of:self), &outCount)
        //解包
        guard let propertyList = property else {
            return list
        }
        
        for i in 0 ..< Int(outCount){
            //取出單個屬性
            let property = propertyList[i]
            
            //獲取屬性的名字
            guard let char_f = property_getName(property) else{
                continue
            }
            //轉(zhuǎn)換為String
            if let key = NSString(cString: char_f, encoding: String.Encoding.utf8.rawValue) as? String {
                //添加到數(shù)組
                list.append(key)
            }
        }
        return list
    }
    
    func archiverWithRootObject(_ rootObjcet : Any){
        let filePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last!
        
        let fileName = NSStringFromClass(self.classForCoder) as String
        
        let savePath = filePath + "/" + fileName + ".plist"
        
        //歸檔
        NSKeyedArchiver.archiveRootObject(rootObjcet, toFile:savePath)
    }
    
    func unarchiver()->Any?{
        let filePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last!
        
        let fileName = NSStringFromClass(self.classForCoder) as String
        
        let savePath = filePath + "/" + fileName + ".plist"
        
        //解檔出來的元素
        return NSKeyedUnarchiver.unarchiveObject(withFile: savePath)
    }
}

巨坑

Swift的巨坑!!!...哭了一下午,一直在解檔崩潰.最后發(fā)現(xiàn)問題在歸檔.

//下面兩種歸檔的方法要注意了.不要使用第一種歸檔.
    ~~aCoder.encode(object: Any?)~~  警告,不要使用
//而第二種方法因為第一個參數(shù)沒有外部參數(shù),很難打出來.
    aCoder.encode(objv: Any?, forKey: String)
    //輸入aCoder.encodeforkey 來查找這個方法

因為本來用OC寫的,嘗試翻譯成Swift的時候出現(xiàn)這么一個坑.望大家引起注意.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末梦湘,一起剝皮案震驚了整個濱河市友多,隨后出現(xiàn)的幾起案子盾剩,更是在濱河造成了極大的恐慌,老刑警劉巖只壳,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件关面,死亡現(xiàn)場離奇詭異蜕青,居然都是意外死亡瘟栖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門蜡豹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來麸粮,“玉大人,你說我怎么就攤上這事镜廉∨澹” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵娇唯,是天一觀的道長齐遵。 經(jīng)常有香客問我凤巨,道長,這世上最難降的妖魔是什么洛搀? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任敢茁,我火速辦了婚禮,結(jié)果婚禮上留美,老公的妹妹穿的比我還像新娘彰檬。我一直安慰自己,他們只是感情好谎砾,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布逢倍。 她就那樣靜靜地躺著,像睡著了一般景图。 火紅的嫁衣襯著肌膚如雪较雕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天挚币,我揣著相機與錄音亮蒋,去河邊找鬼。 笑死妆毕,一個胖子當著我的面吹牛慎玖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笛粘,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼趁怔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了薪前?” 一聲冷哼從身側(cè)響起润努,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎示括,沒想到半個月后铺浇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡例诀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年随抠,在試婚紗的時候發(fā)現(xiàn)自己被綠了裁着。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片繁涂。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖二驰,靈堂內(nèi)的尸體忽然破棺而出扔罪,到底是詐尸還是另有隱情,我是刑警寧澤桶雀,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布矿酵,位于F島的核電站唬复,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏全肮。R本人自食惡果不足惜敞咧,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辜腺。 院中可真熱鬧休建,春花似錦、人聲如沸评疗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽百匆。三九已至砌些,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間加匈,已是汗流浹背存璃。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雕拼,地道東北人有巧。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像悲没,于是被迫代替她去往敵國和親篮迎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫示姿、插件甜橱、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評論 4 62
  • 今年的7月并不是一個特別適合黃山的季節(jié),在上海是梅雨季栈戳,而在黃山正處于水患時候岂傲,為了友誼的小船,我們毅然決然迎風...
    天_空_閱讀 836評論 2 2
  • 昨夜城門落雨 竹林芭蕉染銅綠 花經(jīng)凄雨 零落滿鳧徑 心猿意馬的把舊衣收起 忘了 今日要見滿意華發(fā)的你 自書里 不覺...
    白箋閱讀 339評論 0 1