美文网首页
学习笔记1:归档解档、runtime

学习笔记1:归档解档、runtime

作者: 码农小白 | 来源:发表于2016-07-13 09:11 被阅读87次

    系统类型

    1.归解档字符串

    两者都需要先拼出文件路径:
    归档

    NSString *path = [docPath stringByAppendingPathComponent:@"myStr"];
    [NSKeyedArchiver archiveRootObject:@"我是字符串" toFile:path];
    

    解档

    NSString *path = [docPath stringByAppendingPathComponent:@"myStr"];
    NSString *str = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    

    2.归解档数组

    两者都需要先拼出文件路径:
    归档

    NSString *path = [docPath stringByAppendingPathComponent:@"myArray"];
    [NSKeyedArchiver archiveRootObject:@[@"元素1", @"元素2", @"元素3" toFile:path];
    

    解档

    NSString *path = [docPath stringByAppendingPathComponent:@"myArray"];
    NSString *str = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    

    3.归解档字典

    两者都需要先拼出文件路径:
    归档

    NSString *path = [docPath stringByAppendingPathComponent:@"myDic"];
    [NSKeyedArchiver archiveRootObject:@{key:value};
    

    解档

    NSString *path = [docPath stringByAppendingPathComponent:@"myDic"];
    NSString *str = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    

    自定义类型(两种方法)

    例:现有一student学生类具有以下属性:

    @property (nonatomic) NSString *name;
    @property (nonatomic) NSString *sex;
    @property (nonatomic) NSUInteger age;
    @property (nonatomic) NSString *school;
    @property (nonatomic) BOOL marry;
    @property (nonatomic) NSString *className;
    @property (nonatomic) NSString *favor;
    @property (nonatomic) NSString *skill;
    @property (nonatomic) NSString *score;
    

    要想对该学生类实现归档和解档,就一定要实现<NSCoding>协议,该协议中只有两个方法:即要归档的属性和要解档的属性。

    方法一:

    归档

    - (void)encodeWithCoder:(NSCoder *)aCoder{
        [aCoder encodeObject:_name forKey:@"name"];
        [aCoder encodeInteger:_age forKey:@"age"];
        [aCoder encodeObject:_sex forKey:@"sex"];
        [aCoder encodeObject:_favor forKey:@"favor"];
        [aCoder encodeObject:_score forKey:@"score"];
        [aCoder encodeObject:_skill forKey:@"skill"];
        [aCoder encodeObject:_school forKey:@"school"];
        [aCoder encodeObject:_className forKey:@"className"];
        [aCoder encodeBool:_marry forKey:@"marray"];
    }
    

    对应的解档

    - (instancetype)initWithCoder:(NSCoder *)aDecoder{
        if (self = [super init]) {
            self.name = [aDecoder decodeObjectForKey:@"name"];
            self.age = [aDecoder decodeIntegerForKey:@"age"];
            self.sex = [aDecoder decodeObjectForKey:@"sex"];
            self.favor = [aDecoder decodeObjectForKey:@"favor"];
            self.score = [aDecoder decodeObjectForKey:@"score"];
            self.skill = [aDecoder decodeObjectForKey:@"skill"];
            self.school = [aDecoder decodeObjectForKey:@"school"];
            self.className = [aDecoder decodeObjectForKey:@"className"];
            self.marry = [aDecoder decodeBoolForKey:@"marray"];
        }
        return self;
    }
    

    由于方法一过于单一,遇到属性过多的情况时不能轻松解决,所以需要使用另一种方法来解决(runtime).

    方法二:Runtime机制

    需要引入runtime库#import <objc/runtime.h>
    归档

    - (void)encodeWithCoder:(NSCoder *)aCoder{
        // Ivar: 成员变量
        // class_copyIvarList: 拷贝参数一的类的所有属性列表出来,第二参数中会被存入列表中的元素数量
        unsigned int outCount = 0;
        Ivar *varList = class_copyIvarList(self.class, &outCount);
        for (int i = 0; i < outCount; i++) {
            // 从列表中获取每一个成员变量
            Ivar var = varList[i];
            // 获取成员变量的名字
            const char *name = ivar_getName(var);
            // C字符串 -> OC字符串
            NSString *propertyName = [NSString stringWithUTF8String:name];
            NSLog(@"%@", propertyName);
            // KVC
            id value = [self valueForKey:propertyName];
            // 归档
            [aCoder encodeObject:value forKey:propertyName];
        }
        // C语言在用完之后手动进行释放
        free(varList);
    }
    

    解档

    - (instancetype)initWithCoder:(NSCoder *)aDecoder{
        if (self = [super init]) {
                // 1.复制属性列表
            unsigned int outCount = 0;
            Ivar *varList = class_copyIvarList(self.class, &outCount);
                // 2.for循环对每个成员变量进行操作
            for (int i = 0; i < outCount; i++) {
                // 3.获取成员变量名,转换成OC的名字
                Ivar var = varList[i];
                const char *name = ivar_getName(var);
                NSString *pName = [NSString stringWithUTF8String:name];
                // 4.通过属性名解档出对应的值
                id value = [aDecoder decodeObjectForKey:pName];
                // 5.通过KVC方式,把值存储到对应的属性中
                [self setValue:value forKey:pName];
            }
            
            free(varList);
        }
        return self;
    }
    

    可以将description、归档、解档定义为宏。以下以description为例,归档和解档同样定义。

    // 宏中的‘\’作用是换行,表示接下来一行也是宏的内容
    #define kDescription \
    - (NSString *)description{\
        NSMutableString *str = [NSMutableString new];\
        unsigned int outCount = 0;\
        Ivar *varList = class_copyIvarList(self.class, &outCount);\
        for (int i = 0; i < outCount; i++) {\
            Ivar var = varList[i];\
            const char *name = ivar_getName(var);\
            NSString *pName = [NSString stringWithUTF8String:name];\
            id obj = [self valueForKey:pName];\
            [str appendFormat:@"%@:%@", pName, obj];\
        }\
        free(varList);\
        return str;\
    }
    

    runtime为系统类添加属性

    例:为一个button添加一个name属性,用来存储button的名字。

    创建一个UIButton的分类UIButton+Custom,在.h声明一个名字属性
    @property (nonatomic) NSString *name;
    .m文件中引入#import <objc/runtime.h>,实现setget方法:

    - (void)setName:(NSString *)name{
        // 绑定参数3到参数1的键-参数2上, 内存管理的方式是参数4
        // 参数2是方法的指针地址,每个方法的指针地址是唯一的
        objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    - (NSString *)name{
        // 获取参数1中key是当前方法的指针对应的值
        // _cmd 可以获取所在的方法指针
        return objc_getAssociatedObject(self, _cmd);
    }
    

    更换类型

    runtime可以更换对象的类型(OC无法实现的时候)

    例:将tableView的类型转换为第三方TPKeyboardAvoidingTableView类型

    // 使用runtime替换tableView的类型
    // 把参数一的类型变成参数2的类型
    object_setClass(self.tableView, [TPKeyboardAvoidingTableView class]);
    

    相关文章

      网友评论

          本文标题:学习笔记1:归档解档、runtime

          本文链接:https://www.haomeiwen.com/subject/tblsjttx.html