使用runtime歸檔模型對(duì)象

在開發(fā)中經(jīng)常需要對(duì)一些對(duì)象進(jìn)行保存,當(dāng)然這是一些很輕量級(jí)的,我們首先會(huì)想到使用NSUserDefaults進(jìn)行保存,但是NSUserDefaults所能直接保存的對(duì)象類型也是有限的,比如NSArray,NSData,NSDictionary,NSNumber,NSString,對(duì)于我們自己建立的模型對(duì)象,NSUserDefaults直接保存的話,就有點(diǎn)力不從心了,這時(shí),我們往往要對(duì)模型對(duì)象進(jìn)行歸檔,歸檔雖說(shuō)實(shí)現(xiàn)簡(jiǎn)單,但是,試想一些,如果你的模型成員比較多,手動(dòng)實(shí)現(xiàn)很費(fèi)時(shí)間,可以新建一個(gè)NSObject的分類,使用runtime遍歷屬性實(shí)現(xiàn)歸檔

. h 文件
//
//  DVVCoding.h
//  DVVCoding <https://github.com/devdawei/DVVCoding.git>
//
//  Created by 大威 on 2016/11/21.
//  Copyright ? 2016年 devdawei. All rights reserved.
//

#import <Foundation/Foundation.h>

@protocol DVVCodingDelegate <NSObject>

@optional

/**
 如果有不想緩存的屬性,通過此代理方法返回就可以了
 */
+ (NSArray *)dvv_codingIgnoreProperties;

@end

@interface NSObject (DVVCoding)

/**
 *  解碼(從文件解析對(duì)象)
 */
- (void)dvv_decode:(NSCoder *)decoder;
/**
 *  編碼(將對(duì)象寫入文件)
 */
- (void)dvv_encode:(NSCoder *)encoder;


/**
 *  屬性歸檔的實(shí)現(xiàn)
 */
#define DVVCodingImplementation \
- (instancetype)initWithCoder:(NSCoder *)aDecoder \
{ \
self = [super init]; \
if (self) { \
[self dvv_decode:aDecoder]; \
} \
return self; \
} \
\
- (void)encodeWithCoder:(NSCoder *)coder \
{ \
[self dvv_encode:coder]; \
}

@end
. m 文件
//
//  DVVCoding.m
//  DVVCoding <https://github.com/devdawei/DVVCoding.git>
//
//  Created by 大威 on 2016/11/21.
//  Copyright ? 2016年 devdawei. All rights reserved.
//

#import "DVVCoding.h"
#import <objc/runtime.h>

typedef NS_ENUM(NSUInteger, DVVCodingType)
{
    DVVCodingTypeEncode,
    DVVCodingTypeDecode,
};

@implementation NSObject (DVVCoding)


- (void)dvv_encode:(NSCoder *)encoder
{
    [self dvv_codingFor:encoder type:DVVCodingTypeEncode];
}

- (void)dvv_decode:(NSCoder *)decoder
{
    [self dvv_codingFor:decoder type:DVVCodingTypeDecode];
}

- (void)dvv_codingFor:(NSCoder *)coder type:(DVVCodingType)type
{
    NSArray *ignoreProperties = nil;
    if ([[self class] respondsToSelector:@selector(dvv_codingIgnoreProperties)])
    {
        ignoreProperties = (NSArray *)[[self class] performSelector:@selector(dvv_codingIgnoreProperties)];
    }
    
    if (!ignoreProperties) ignoreProperties = [NSArray array];
    // 添加默認(rèn)忽略的屬性
    NSMutableArray *defaultIgnoreProperties = [NSMutableArray arrayWithObjects:@"hash", @"superclass", @"description", @"debugDescription", nil];
    ignoreProperties = [defaultIgnoreProperties arrayByAddingObjectsFromArray:ignoreProperties];
    
    unsigned int count;
    // 獲取屬性列表
    objc_property_t *properties = class_copyPropertyList(self.class, &count);
    
    for (unsigned int i = 0; i < count; i++)
    {
        // 獲取一個(gè)屬性
        objc_property_t property = properties[i];
        // 獲取一個(gè)屬性名
        const char *name = property_getName(property);
        NSString *propertyName = [NSString stringWithUTF8String:name];
        
        // 過濾屬性
        if (ignoreProperties)
        {
            BOOL flage = NO;
            for (NSString *ignorePropertyName in ignoreProperties)
            {
                if ([propertyName isEqualToString:ignorePropertyName])
                {
                    flage = YES;
                    break;
                }
            }
            if (flage)
            {
                continue;
            }
        }
        
        // 用來(lái)存儲(chǔ)一個(gè)屬性值
        NSString *propertyValue = nil;
        
        // 編碼
        if (DVVCodingTypeEncode == type)
        {
            propertyValue = [self valueForKey:propertyName];
            if(propertyValue) [coder encodeObject:propertyValue forKey:propertyName];
        }
        // 解碼
        else if (DVVCodingTypeDecode == type)
        {
            propertyValue = [coder decodeObjectForKey:propertyName];
            if(propertyValue) [self setValue:propertyValue forKey:propertyName];
        }
    }
    // 釋放
    free(properties);
}

@end
直接在模型對(duì)象的implementation里調(diào)用宏
#import "MMRDMUserInfo.h"

@implementation MMRDMUserInfo

// 調(diào)用這句宏定義,即可實(shí)現(xiàn)對(duì)象歸檔,不用自己再對(duì)每一個(gè)屬性寫繁瑣的編碼和解碼
DVVCodingImplementation

/**
 如果有不想緩存的屬性,通過此代理方法返回

 @return 忽略列表
 */
+ (NSArray *)dvv_codingIgnoreProperties
{
    return @[ @"property_1", @"property_2" ];
}

@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,624評(píng)論 30 472
  • 轉(zhuǎn)載自:http://www.mamicode.com/info-detail-957988.html 1、iOS...
    哆啦_閱讀 2,435評(píng)論 0 2
  • iOS 開発の結(jié)構(gòu) 畫面 UI UIWebview [[UIApplication sharedApplicati...
    RencaiXiong閱讀 670評(píng)論 0 0
  • Maybe,I am sensitive. 我對(duì)光線有一種近乎偏執(zhí)的“挑剔”。每天睡覺前,我總會(huì)讓舍友把臺(tái)燈調(diào)暗一...
    看云的LJH閱讀 696評(píng)論 1 4
  • 有一種愛 不是男女之情 是你們待我如知己 我視你們?nèi)缬H人 有一種愛 不是血緣之系 是你們待我如初心 我視你們?nèi)缬篮?..
    小灰兔講故事閱讀 270評(píng)論 1 3

友情鏈接更多精彩內(nèi)容