使用带有运行时反射的 NSCoder 和 NSKeyedArchiver 来深度复制自定义类 [英] Using NSCoder and NSKeyedArchiver with runtime reflection to deep copy a custom class

查看:52
本文介绍了使用带有运行时反射的 NSCoder 和 NSKeyedArchiver 来深度复制自定义类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用

- (id)initWithCoder:(NSCoder *)coder

- (void)encodeWithCoder:(NSCoder *)coder

编码用于复制的自定义类(使用 NSKeyedArchiver 等)

to encode a custom class for copying (using NSKeyedArchiver etc)

我的自定义类包含大量 iVar.我不想在编码代码中列出所有这些,我想使用反射来简单地枚举自定义类中的所有属性,并在循环中对每个属性进行编码/解码.

My custom class contains a large number of iVars. Instead of listing all of these in the encoding code I'd like to use reflection to simply enumerate over all the properties in the custom class and encode/decode each property from within a loop.

我最终会得到看起来有点像这样的代码:

I'll end up with code that looks a bit like this:

- (id)initWithCoder:(NSCoder *)coder
{
    if ((self = [super init]))
    {
        [self codeWithCoder:coder andDirection:0];
    }
}
- (void)encodeWithCoder:(NSCoder *)coder
{
    [self codeWithCoder:coder andDirection:1];
}

-(void)codeWithCoder:(NSCoder *)coder andDirection:(NSInteger)direction
{
    unsigned count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);



    unsigned i;
    for (i = 0; i < count; i++)
    {
        objc_property_t property = properties[i];
        NSString *name = [NSString stringWithUTF8String:property_getName(property)];
        const char * type = property_getAttributes(property);
        NSString * typeString = [NSString stringWithUTF8String:type];
        NSArray * attributes = [typeString componentsSeparatedByString:@","];
        NSString * typeAttribute = [attributes objectAtIndex:0];
        NSString * propertyType = [typeAttribute substringFromIndex:1];
        const char * rawPropertyType = [propertyType UTF8String];

        if (strcmp(rawPropertyType, @encode(float)) == 0) {
            //it's a float
            if (direction==0) ??? = [coder decodeFloatForKey:name];
            else [coder encodeFloat:???? forKey:name];

        } else if (strcmp(rawPropertyType, @encode(bool)) == 0) {
            //it's a bool
            if (direction==0) ??? = [coder decodeBoolForKey:name];
            else [coder encodeBool:???? forKey:name];

        } else if (strcmp(rawPropertyType, @encode(int)) == 0) {
            //it's an int
            if (direction==0) ??? = [coder decodeIntegerForKey:name];
            else [coder encodeInteger:???? forKey:name];

        } else if (strcmp(rawPropertyType, @encode(id)) == 0) {
            //it's some sort of object
            if (direction==0) ??? = [coder decodeObjectForKey:name];
            else [coder encodeObject:???? forKey:name];

        }
    }

    free(properties);





}

我的问题是:我该替换什么???和 ????用于获取和设置实际 ivar 值的片段?

My question is this: what do I replace the ??? and ???? fragments with to get and set the actual ivar values?

推荐答案

您是否尝试过:

object_setInstanceVariable
object_setIvar

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/ObjCRuntimeRef/

您可能希望调用 class_copyIvarList 而不是属性版本 - 根据您的用例,仅获取属性可能会错过 IVars.你的超类也采用NSCoding吗?您必须调用 initWithCoder 和 encodeWithCoder 的超级实现.还要注意 class_copyIvarList 和 class_copyPropertyList 只返回在当前类中定义的东西,而不是超类.

You might want to be calling class_copyIvarList instead of the property version - just getting properties might miss IVars depending on your use case. Also does your super class adopt NSCoding? You'll have to call the super implementations of initWithCoder and encodeWithCoder. Note also that class_copyIvarList and class_copyPropertyList only return things defined in the current class, not the super class.

这篇关于使用带有运行时反射的 NSCoder 和 NSKeyedArchiver 来深度复制自定义类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆