zoukankan      html  css  js  c++  java
  • IOS利用objc/runtime和KVC——快速归档解档

      开发过程中有时需要存储一些轻量级的数据,对于IOS提供的几种数据存储方式在这时最合适当属对象归档:NSCoding

      但是将对象数据进行归档解档时候需要实现两个方法: encodeWithCoder和initWithEncoder。encodeWithCoder就是编码,initWithCoder就是解码。

    encodeWithCoder方法传入的是一个NSCoder对象,实现的时候我们就可以调用encodeObject、encodeFloat、 encodeInt等各种方法并通过指定键值进行编码,而

    在需要的时候调用decodeDoubleForKey,decodeFloatForKey,decodeObjectForKey进行解码。

      1.实现encodeWithCoder和initWithEncoder

    #import "MyModel.h"
    
    @implementation MyModel
    
    #define kCUSTIDKey @"CUSTIDKey"
    #define kCUSTSTATUSKey @"CUSTSTATUSKey"
    #define kPICTUREIDKey @"PICTUREIDKey"
    #define kUNITNUMKey @"UNITNUMKey"
    #define kCITYIDKey @"CITYIDKey"
    #define kCUSTNAMEKey @"CUSTNAMEKey"
    #define kCOMMUNITYNAMEKey @"COMMUNITYNAMEKey"
    #define kRESERVE1Key @"RESERVE1Key"
    #define kCITYKey @"CITYKey"
    #define kCOMMUNITYIDKey @"COMMUNITYIDKey"
    #define kCITYNAMEKey @"CITYNAMEKey"
    #define kBUILDINGNUMKey @"BUILDINGNUMKey"
    #define kNICKNAMEKey @"NICKNAMEKey"
    #define kHOUSENUMKey @"HOUSENUMKey"
    #define kPHONEKey @"PHONEKey"
    
    //归档
    - (void)encodeWithCoder:(NSCoder *)aCoder
    {
        [aCoder encodeObject:self.CUSTID forKey:kCUSTIDKey];
        [aCoder encodeObject:self.CUSTSTATUS forKey:kCUSTSTATUSKey];
        [aCoder encodeObject:self.PICTUREID forKey:kPICTUREIDKey];
        [aCoder encodeObject:self.UNITNUM forKey:kUNITNUMKey];
        [aCoder encodeObject:self.PHONE forKey:kPHONEKey];
        [aCoder encodeObject:self.CITYID forKey:kCITYIDKey];
        [aCoder encodeObject:self.CUSTNAME forKey:kCUSTNAMEKey];
        [aCoder encodeObject:self.COMMUNITYNAME forKey:kCOMMUNITYNAMEKey];
        [aCoder encodeObject:self.RESERVE1 forKey:kRESERVE1Key];
        [aCoder encodeObject:self.CITY forKey:kCITYKey];
        [aCoder encodeObject:self.COMMUNITYID forKey:kCOMMUNITYIDKey];
        [aCoder encodeObject:self.CITYNAME forKey:kCITYNAMEKey];
        [aCoder encodeObject:self.BUILDINGNUM forKey:kBUILDINGNUMKey];
        [aCoder encodeObject:self.NICKNAME forKey:kNICKNAMEKey];
        [aCoder encodeObject:self.HOUSENUM forKey:kHOUSENUMKey];
    }
    
    // 解档
    - (id)initWithCoder:(NSCoder *)decoder
    {
        if (self = [super init]) {
            self.CUSTID = [decoder decodeObjectForKey:kCUSTIDKey];
            self.CUSTSTATUS = [decoder decodeObjectForKey:kCUSTSTATUSKey];
            self.PICTUREID = [decoder decodeObjectForKey:kPICTUREIDKey];
            self.PHONE = [decoder decodeObjectForKey:kPHONEKey];
            self.UNITNUM = [decoder decodeObjectForKey:kUNITNUMKey];
            self.CITYID = [decoder decodeObjectForKey:kCITYIDKey];
            self.CUSTNAME = [decoder decodeObjectForKey:kCUSTNAMEKey];
            self.COMMUNITYNAME = [decoder decodeObjectForKey:kCOMMUNITYNAMEKey];
            self.RESERVE1 = [decoder decodeObjectForKey:kRESERVE1Key];
            self.CITY = [decoder decodeObjectForKey:kCITYKey];
            self.COMMUNITYID = [decoder decodeObjectForKey:kCOMMUNITYIDKey];
            self.CITYNAME = [decoder decodeObjectForKey:kCITYNAMEKey];
            self.BUILDINGNUM = [decoder decodeObjectForKey:kBUILDINGNUMKey];
            self.NICKNAME = [decoder decodeObjectForKey:kNICKNAMEKey];
            self.HOUSENUM = [decoder decodeObjectForKey:kHOUSENUMKey];
        }
        return self;
    }
    @end

      写完之后发现整个人都不好了,如果对象属性更多,这些重复性的代码也意味着要被Command+C Command+V着N次,累觉无爱。

      然后尝试用其他方式进行,既然Objective-C运行时库提供了非常便利的方法获取其对象运行时所属类及其所有成员变量,并通过KVC进行值的存取,那么或者可以这样objc/runtime+KVC

      导入#import <objc/runtime.h>头文件

    //获取类中所有属性
        unsigned int count;
        Ivar *varA = class_copyIvarList([MyModel class], &count);
        for (unsigned int i=0; i<count; i++) {
            Ivar v = varA[i];
            const char *name = ivar_getName(v);
            NSLog(@"%s==",name);
        }

      打印LOG:

        

      好用,继续,利用KVC进行取值,根据属性名称获取对应的值

      //KVC取值
            id value = [self valueForKey:strName];
            [encoder encodeObject:value forKey:strName];

      最终改后的程序:

    #import "MyModel.h"
    #import <objc/runtime.h>
    
    @implementation MyModel
    
    //解档
    - (id)initWithCoder:(NSCoder *)decoder
    {
        if (self = [super init]) {
            unsigned int count = 0;
            //获取类中所有成员变量名
            Ivar *ivar = class_copyIvarList([MyModel class], &count);
            for (int i = 0; i<count; i++) {
                Ivar iva = ivar[i];
                const char *name = ivar_getName(iva);
                NSString *strName = [NSString stringWithUTF8String:name];
                //进行解档取值
                id value = [decoder decodeObjectForKey:strName];
                //利用KVC对属性赋值
                [self setValue:value forKey:strName];
            }
            free(ivar);
        }
        return self;
    }
    //归档
    - (void)encodeWithCoder:(NSCoder *)encoder
    {
        unsigned int count;
        Ivar *ivar = class_copyIvarList([MyModel class], &count);
        for (int i=0; i<count; i++) {
            Ivar iv = ivar[i];
            const char *name = ivar_getName(iv);
            NSString *strName = [NSString stringWithUTF8String:name];
            //利用KVC取值
            id value = [self valueForKey:strName];
            [encoder encodeObject:value forKey:strName];
        }
        free(ivar);
    }
    @end

    妥妥的了,远离重复,做开心玩耍的程序媛!

  • 相关阅读:
    Kafka(Go)系列(一)通过dockercompose 安装 Kafka
    grpc通过自签CA证书、server、client双向认证【支持go1.15】
    Go 基准测试和性能测试学习使用
    Debian关闭防火墙
    服务依赖开闭简单算法
    Hbase 和 Hive 的区别,各自使用场景。
    VMware虚拟机 Ubuntu1404
    安装protoc
    Redis大 key 自动过期的问题
    MySQL设置数据库为只读
  • 原文地址:https://www.cnblogs.com/youmomo/p/4244698.html
Copyright © 2011-2022 走看看