一句話 利用runtime輕松實(shí)現(xiàn) 歸檔解檔

先奉上demo的地址

https://github.com/MyHZ/HZCoding.git
使用cocoapods
pod 'NSObject+HZCoding'

我們?cè)陂_發(fā)中存儲(chǔ)數(shù)據(jù)的時(shí)候,經(jīng)常要用的就是歸檔和解檔,我們會(huì)在需要操作的對(duì)象所在的類中實(shí)現(xiàn)兩個(gè)方法粉铐。

-(void)encodeWithCoder:(NSCoder *)aCoder;
-(instancetype)initWithCoder:(NSCoder *)aDecoder;

在這兩個(gè)方法中乃摹,我們會(huì)分別調(diào)用如下兩個(gè)方法對(duì)每個(gè)屬性進(jìn)行操作

- (void)encodeObject:(nullable id)objv forKey:(NSString *)key;
- (nullable id)decodeObjectForKey:(NSString *)key;

當(dāng)然還有其他類型的

- (void)encodeBool:(BOOL)boolv forKey:(NSString *)key;
- (void)encodeInt:(int)intv forKey:(NSString *)key;

然后將需要存儲(chǔ)的屬性 一個(gè)一個(gè)的寫進(jìn)去,而且其中的key又是NSString類型勇劣,我們還要保證 歸檔和解檔時(shí) key是一致的。

上面的方法,是我們一貫的做法拥诡。

開發(fā)中,當(dāng)有一兩個(gè)屬性的時(shí)候(如下)氮发,很簡單渴肉,幾句話復(fù)制一下,再改屬性和key值爽冕。

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

但是我們?cè)趯?shí)際開發(fā)中仇祭,當(dāng)然不止有這一兩個(gè)屬性,也不只是NSString和int類型颈畸,我們難道要復(fù)制 屬性個(gè)數(shù) * 2 遍嗎乌奇?

@property(nonatomic,assign) int age;
@property(nonatomic,assign) int age1;
@property(nonatomic,assign) int age2;
@property(nonatomic,assign) int age3;

當(dāng)然没讲,有人愿意做,那這也是沒辦法礁苗,有耐心爬凑,但是出錯(cuò)了,就有的受了寂屏。


接下來贰谣,我們就用runtime來實(shí)現(xiàn) 歸檔解檔

1.我們新建一個(gè)Person類,最重要的當(dāng)然是需要

<NSCoding>協(xié)議了

@interface Person : NSObject<NSCoding>

@property(nonatomic,copy) NSString *name;
@property(nonatomic,assign) int age;
@property(nonatomic,assign) int age1;
@property(nonatomic,assign) int age2;
@property(nonatomic,assign) int age3;

@end

重點(diǎn)在于:runtime
首先是 歸檔
Peroson.m中

-(void)encodeWithCoder:(NSCoder *)aCoder
{
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList([Person class], &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];
        const char *name = ivar_getName(ivar);
        NSString *key = [[NSString alloc]initWithUTF8String:name];
        [aCoder encodeObject:[self valueForKey:key] forKey:key];
    }
}

class_copyIvarList 獲的所有的屬性
我們通過runtime獲取到所有的屬性名(name)迁霎,
然后得到我們需要?dú)w檔時(shí)用到的key(NSString *key)吱抚,
再使用 KVC 獲得歸檔時(shí)用到的encodeObject ([self valueForKey:key] key在剛才已經(jīng)得到了),

  //歸檔:
  [aCoder encodeObject:[self valueForKey:key] forKey:key];

解檔

-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self) {
        
        unsigned int count = 0;
        Ivar *ivars = class_copyIvarList([Person class], &count);
        for (int i = 0; i < count; i++) {
            Ivar ivar = ivars[i];
            const char *name = ivar_getName(ivar);
            NSString *key = [[NSString alloc]initWithUTF8String:name];
            id value = [aDecoder decodeObjectForKey:key];
            [self setValue:value forKey:key];
        }
        
    }
    return self;
}

核心部分(獲取屬性名 key)都是和歸檔是一樣的考廉,在接檔的時(shí)候秘豹,同樣是使用KVC 獲得屬性值 [self setValue:value forKey:key];


接下來,我們就可以直接使用Person 類了

歸檔

 Person *person = [Person new];
    person.name = @"zhangsan";
    person.age = 18;
    
    NSString *temp = NSTemporaryDirectory();
    temp = [temp stringByAppendingPathComponent:@"zhangsan.plist"];
    [NSKeyedArchiver archiveRootObject:person toFile:temp];

解檔

NSString *temp = NSTemporaryDirectory();
    temp = [temp stringByAppendingPathComponent:@"zhangsan.plist"];
    Person *person = (Person *)[NSKeyedUnarchiver unarchiveObjectWithFile:temp];
    NSLog(@"%@ %d",person.name,person.age);

到此昌粤,就算是完成了Person的歸檔和解檔既绕。


好吧,我又該但是了涮坐,我們肯定也不只是Person 這一個(gè)類吧凄贩,然后每個(gè)類再復(fù)制一次?那當(dāng)然不是了袱讹。

我們會(huì)有更簡單的方法

1.首先
我們新建一個(gè)NSObject的類別
寫兩個(gè)方法
NSObject+HZCoding

@interface NSObject (HZCoding)

-(void)HZ_encode:(NSCoder *)aCoder;
-(void)HZ_decode:(NSCoder *)aDecoder;

@end

2.接下來 我們?cè)?m中導(dǎo)入

#import <objc/message.h>

3.然后我們實(shí)現(xiàn)上面的兩個(gè)方法

-(void)HZ_encode:(NSCoder *)aCoder
{
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList([self class], &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];
        const char *name = ivar_getName(ivar);
        NSString *key = [[NSString alloc]initWithUTF8String:name];
        [aCoder encodeObject:[self valueForKey:key] forKey:key];
    }
}

-(void)HZ_decode:(NSCoder *)aDecoder
{
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList([self class], &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];
        const char *name = ivar_getName(ivar);
        NSString *key = [[NSString alloc]initWithUTF8String:name];
        id value = [aDecoder decodeObjectForKey:key];
        [self setValue:value forKey:key];
    }
}

@end

4.把我們之前寫的Person的那段代碼刪掉疲扎,我們重新搞Person

-(void)encodeWithCoder:(NSCoder *)aCoder
{
}

-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
}

畢竟我們?cè)贜SObject+HZCoding已經(jīng)定義了那些個(gè)實(shí)現(xiàn)的方法,而我們的類 都是繼承自NSObject的捷雕,那我們直接在自己的類中調(diào)用NSObject的方法椒丧,不是更方便嘛。
上代碼

導(dǎo)入

#import "NSObject+HZCoding.h"
-(void)encodeWithCoder:(NSCoder *)aCoder
{
    [self HZ_encode:aCoder];
}

-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {
        [self HZ_decode:aDecoder];
    }return self;
}

好了救巷,這樣子又方便了一些壶熏,幾句話就完成了,我們每個(gè)類只需要導(dǎo)入之前的類別(NSObject+HZCoding)浦译,調(diào)用里面的方法棒假,就可以完成了。


你們猜精盅,有但是沒有帽哑?

還有

但是 我們還是嫌麻煩,每個(gè)類還是要重新寫這幾行字渤弛,我不想寫啊。

接下來也不算是黑魔法甚带,也不是什么高大上的萬一她肯,我們用宏定義佳头,把這段話給定義好,用到的時(shí)候晴氨,直接宏定義調(diào)用不就好了康嘉。
在NSObject+HZCoding.h里面 我們定義下面的內(nèi)容

#define HZCodingImplementation \
-(void)encodeWithCoder:(NSCoder *)aCoder\
{\
    [self HZ_encode:aCoder];\
}\
-(instancetype)initWithCoder:(NSCoder *)aDecoder\
{\
    if (self = [super init]) {\
        [self HZ_decode:aDecoder];\
    }return self; \
}

接下來就是關(guān)鍵的代碼了

重新回到我們的Person類

導(dǎo)入 #import "NSObject+HZCoding.h"
實(shí)現(xiàn):HZCodingImplementation

然后Person.m的代碼就變了這樣子

#import "Person.h"
#import "NSObject+HZCoding.h"

@implementation Person

HZCodingImplementation

@end

使用的方法,是不是越來越簡單了籽前。


總結(jié) 總結(jié) 總結(jié)
總結(jié) 總結(jié) 總結(jié)


用到的時(shí)候直接新建一個(gè)NSObject的類別亭珍,將NSObject+HZCoding里面的內(nèi)容復(fù)制進(jìn)去就好了。

寫的有點(diǎn)亂了枝哄,記住用法就好了

協(xié)議 <NSCoding>
導(dǎo)入 #import "NSObject+HZCoding.h"
宏定義HZCodingImplementation

OK 就是這么多了

講的麻煩 肄梨,不如直接看demo了

利用runtime獲取對(duì)象的所有屬性(值),所有方法
http://www.reibang.com/p/24ff360c0e94

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挠锥,一起剝皮案震驚了整個(gè)濱河市众羡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蓖租,老刑警劉巖粱侣,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蓖宦,居然都是意外死亡齐婴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門稠茂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柠偶,“玉大人,你說我怎么就攤上這事主慰∠荩” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵共螺,是天一觀的道長该肴。 經(jīng)常有香客問我,道長藐不,這世上最難降的妖魔是什么匀哄? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮雏蛮,結(jié)果婚禮上涎嚼,老公的妹妹穿的比我還像新娘。我一直安慰自己挑秉,他們只是感情好法梯,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般立哑。 火紅的嫁衣襯著肌膚如雪夜惭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天铛绰,我揣著相機(jī)與錄音诈茧,去河邊找鬼。 笑死捂掰,一個(gè)胖子當(dāng)著我的面吹牛敢会,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播这嚣,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼鸥昏,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了疤苹?” 一聲冷哼從身側(cè)響起互广,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卧土,沒想到半個(gè)月后惫皱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尤莺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年旅敷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颤霎。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡媳谁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出友酱,到底是詐尸還是另有隱情晴音,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布缔杉,位于F島的核電站锤躁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏或详。R本人自食惡果不足惜系羞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望霸琴。 院中可真熱鬧椒振,春花似錦、人聲如沸梧乘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至夹供,卻和暖如春辑莫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背罩引。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枝笨,地道東北人袁铐。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像横浑,于是被迫代替她去往敵國和親剔桨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

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