You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何序列化未实现NSCoding/NSSecureCoding的外部Objective-C类?

未实现NSCoding/NSSecureCoding的第三方Objective-C对象序列化方案

可以实现,以下是几种可行的方案:

一、基于Runtime手动序列化/反序列化

通过Objective-C Runtime API获取对象的属性或实例变量,手动完成属性值的编码与解码,无需修改第三方类的源码。

示例代码:

// 编码第三方对象
- (void)encodeExternalObject:(id)externalObj toCoder:(NSCoder *)coder {
    unsigned int ivarCount;
    Ivar *ivars = class_copyIvarList([externalObj class], &ivarCount);
    
    for (unsigned int i = 0; i < ivarCount; i++) {
        Ivar ivar = ivars[i];
        const char *ivarName = ivar_getName(ivar);
        NSString *key = [NSString stringWithUTF8String:ivarName];
        id value = [externalObj valueForKey:key];
        
        // 根据属性类型选择对应编码方法,这里以通用对象为例
        [coder encodeObject:value forKey:key];
    }
    free(ivars);
}

// 解码重建第三方对象
- (id)decodeExternalObjectOfClass:(Class)cls fromCoder:(NSCoder *)coder {
    id obj = [[cls alloc] init];
    unsigned int ivarCount;
    Ivar *ivars = class_copyIvarList(cls, &ivarCount);
    
    for (unsigned int i = 0; i < ivarCount; i++) {
        Ivar ivar = ivars[i];
        const char *ivarName = ivar_getName(ivar);
        NSString *key = [NSString stringWithUTF8String:ivarName];
        id value = [coder decodeObjectForKey:key];
        
        [obj setValue:value forKey:key];
    }
    free(ivars);
    return obj;
}

注意事项:

  • 若第三方类的属性是私有成员,通过valueForKey:可能无法直接访问,需结合ivar_getTypeEncoding判断类型后,用object_getIvar直接读取实例变量值。
  • 需处理基本数据类型(如int、float等)的编码,不能一概用encodeObject:。

二、为第三方类添加Category实现Coding协议

通过Category扩展第三方类,实现NSCoding或NSSecureCoding协议的方法,无需侵入原类代码。

示例代码:

// 为第三方类ExternalObjectO添加Coding扩展
@interface ExternalObjectO (Coding) <NSCoding>
@end

@implementation ExternalObjectO (Coding)

- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super init]) {
        // 手动解码并赋值已知属性
        self.title = [coder decodeObjectForKey:@"title"];
        self.count = [coder decodeIntegerForKey:@"count"];
        // 其他属性依次处理
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:self.title forKey:@"title"];
    [coder encodeInteger:self.count forKey:@"count"];
    // 其他属性依次处理
}

@end

注意事项:

  • 需明确知晓第三方类的所有公开属性,若属性是私有的,同样需要借助Runtime API读写。
  • 若第三方类后续版本更新修改了属性,需要同步更新Category的实现。

三、先转字典再序列化

将第三方对象转换为NSDictionary(默认支持NSCoding),再对字典进行序列化;解码时先解析字典,再重建对象。

示例代码:

// 对象转字典
- (NSDictionary *)convertToDictionary:(id)externalObj {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    unsigned int propCount;
    objc_property_t *props = class_copyPropertyList([externalObj class], &propCount);
    
    for (unsigned int i = 0; i < propCount; i++) {
        objc_property_t prop = props[i];
        NSString *propName = [NSString stringWithUTF8String:property_getName(prop)];
        id value = [externalObj valueForKey:propName];
        dict[propName] = value;
    }
    free(props);
    return dict;
}

// 字典转对象
- (id)convertFromDictionary:(NSDictionary *)dict toClass:(Class)cls {
    id obj = [[cls alloc] init];
    for (NSString *key in dict.allKeys) {
        [obj setValue:dict[key] forKey:key];
    }
    return obj;
}

注意事项:

  • 该方法本质是属性的浅拷贝,若对象包含自定义子对象,子对象也需要支持序列化或做同样的转换处理。

内容的提问来源于stack exchange,提问作者jormen651

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 01:05:25