zoukankan      html  css  js  c++  java
  • iOS 自定义对象及子类及模型套模型的拷贝、归档存储的通用代码

    一、runtime实现通用copy

    如果自定义类的子类,模型套模型你真的会copy吗,小心有坑。

    copy需要自定义类继承NSCopying协议

    #import <objc/runtime.h>
    
    - (id)copyWithZone:(NSZone *)zone {
        
        id obj = [[[self class] allocWithZone:zone] init];
        Class class = [self class];
        while (class != [NSObject class]) {
            unsigned int count;
            Ivar *ivar = class_copyIvarList(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] copy];//如果还套了模型也要copy呢
                [obj setValue:value forKey:strName];
            }
            free(ivar);
            
            class = class_getSuperclass(class);//记住还要遍历父类的属性呢
        }
        return obj;
    }

    二、runtime实现通用归档解档

    归档解档需要自定义类继承NSCoding协议

    #import <objc/runtime.h>

    #pragma
    mark - 归档、解档 - (void)encodeWithCoder:(NSCoder *)encoder { Class class = [self class]; while (class != [NSObject class]) { unsigned int count; Ivar *ivar = class_copyIvarList(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); class = class_getSuperclass(class);//记住还要遍历父类的属性呢 } } - (id)initWithCoder:(NSCoder *)decoder { self = [super init]; if (self) { Class class = [self class]; while (class != [NSObject class]) { unsigned int count = 0; //获取类中所有成员变量名 Ivar *ivar = class_copyIvarList(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); class = class_getSuperclass(class);//记住还要遍历父类的属性呢 } } return self; }

    三、NSUserDefaults存储自定义对象

    //1.自定义类继承NSCoding协议,并实现归档解档,前面介绍过了,不多说
    
    //2.将自定义对象转NSData
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:student];
    
    //3.存到NSUserDefaults
    [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"myStudent"];
    [[NSUserDefaults standardUserDefaults] synchronize];//这句要写,很多人都忘了
    
    //4.存数组,数组中包含自定义对象
    [dataArray addObject:data];//这个data是第2步归档得到的data
    
    //5.NSUserDefaults只能存不可变数组,不要忘了转换成不可变
    NSArray * array = [NSArray arrayWithArray:dataArray];
    [[NSUserDefaults standardUserDefaults] setObject:array forKey:@"students"];

    四、NSUserDefaults中读取归档的自定义对象

    NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"myStudent"];
    Student *student = [NSKeyedUnarchiver unarchiveObjectWithData:data];
  • 相关阅读:
    事件委托应用:在父控件中创建子控件,并接收值
    填充树节点
    JAVA Eclipse如何安装Swing
    JAVA Eclipse开发Android如何设置滚动条最大值最小值
    JAVA Eclipse开发Android如何让屏幕保持为竖直或水平状态
    JAVA Eclipse开发Android如何让超出界面的部分自动显示滚动条
    JAVA Eclipse开发Android程序如何自定义图标
    JAVA Eclipse开发Android程序会经常闪退是怎么回事
    JAVA Eclipse的Android文件结构是怎么样的
    JAVA Eclipse的Android的进程和生命周期是什么
  • 原文地址:https://www.cnblogs.com/zhanglinfeng/p/8418407.html
Copyright © 2011-2022 走看看