从 NSDictionary 迁移到 Object 的最佳方式

Posted

技术标签:

【中文标题】从 NSDictionary 迁移到 Object 的最佳方式【英文标题】:Best way to migrate from NSDictionary to Object 【发布时间】:2016-11-18 01:40:03 【问题描述】:

我有一个符合 NSCoding 的对象(并存档到磁盘)。此对象 (myMetrics) 的一个属性是 NSDictionary。在新版本的软件中,我需要向该字典添加一个键,但我需要在应用程序的其余部分使用主对象之前执行此操作,因为它是必需的键。

我的想法是做类似的事情:

-(id)initWithCoder:(NSCoder *)coder

    if (self = [super init])
    
       self.myMetrics = [coder decodeObjectForKey:@"myMetrics"];
       ... other properties go here ....
    

    .... add the new key to myMetrics with default value if it is missing in myMetrics ...

    return (self);

我真正想做的是将 myMetrics 从字典转换为它自己的类。我不确定如何处理已经存在的归档对象。我的想法是:

    添加一个名为 newMetrics 的类 NewMetrics 的新属性。 在 initWithCoder 中,如果找到 myMetrics 属性,则将其数据移动到 newMetrics 属性中 在 encodeWithCoder 中只处理 newMetrics,从不重新编码旧字典。

通过这种方式,软件始终使用 NewMetrics 对象,但 initWithCoder 能够处理旧式 myMetrics。

在保持相同属性名称的同时有什么好的方法吗?

@property (atomic, retain) NSDictionary* myMetrics; //  dictionary of parameters

becomes

@property (atomic, retain) NewMetrics* myMetrics; // parameters

rather than

@property (atomic, retain) NewMetrics* newMetrics; // parameters

有没有更好的办法?

【问题讨论】:

您在某些地方将您的新班级称为NewMetrics,而在其他地方则称为MyMetrics。您可以编辑您的问题以使用其中一个吗? 很抱歉 - 它已修复。 【参考方案1】:

是的,您可以将 myMetrics 从字典转换为自己的类,而无需重命名属性,同时仍处理现有的归档对象。新的属性声明将是:

@property (atomic, retain) NewMetrics* myMetrics; // parameters

initWithCoder: 函数类似于:

-(id)initWithCoder:(NSCoder *)coder

    if (self = [super init])
    
        // decode saved NewMetrics object
        self.myMetrics = [coder decodeObjectForKey:@"newMyMetrics"];
        if (!self.myMetrics) 
            // fall back to legacy saved metrics NSDictionary
            NSDictionary *legacyMetrics = [coder decodeObjectForKey:@"myMetrics"];
            if (legacyMetrics) 
                self.myMetrics = [[NewMetrics alloc] initWithDictionary:legacyMetrics];
             else 
                // handle having no saved metrics
            
        

        ... other properties go here ....
    

    return self;

您必须在新密钥下开始对 myMetrics 属性进行编码,例如@"myNewMetrics",并提供一种将旧式度量字典转换为新的 NewMetrics 类的实例的方法,例如initWithDictionary:如上图。

【讨论】:

是否可以执行以下操作:id tempMetrics = [coder decodeObjectForKey:@"myMetrics"];然后做一个测试 if ([tempMetrics isKindOfClass:[NSDictionary class]]) 这样我就不需要在新键下编码了吗? 你可以这样做,但如果你的应用程序的旧版本试图解码由新版本保存的存档,它可能会崩溃。使用相同的键来引用两种不同类型的数据对我来说是错误的。您是否有某些原因不想使用新密钥? 主要是为了清洁,所以编码键与属性键匹配。 v1 应用程序无法打开 v2 文档还有其他原因(我的 NSDocument 子类会对此进行检查)。感谢您的建议……确实很有帮助。

以上是关于从 NSDictionary 迁移到 Object 的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

从 Objective-C 迁移到 Swift:AFNetworking > Alamofire

将原生 iOS 应用的数据迁移到 React Native 应用的异步存储

JSON数据从OSS迁移到MaxCompute最佳实践

在 Swift 中访问 object-c NSDictionary 值很慢

核心数据模型版本控制和数据迁移

从 NSDictionary 保存数据到 NSDictionary