如何序列化未实现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
相关产品推荐
相关产品推荐

