【问题标题】:Using enums with Core Data将枚举与核心数据一起使用
【发布时间】:2011-11-21 14:10:14
【问题描述】:

处理辅助表的最佳方式是什么(我认为有一个更专业的词,但目前它正在逃避我)?例如,我的名为 Entity 的对象有一个 entity_type 属性。该 entity_type 需要一个字符串描述。假设只有少数几种可能的 entity_types。

所以我可以看到几种方法:

  1. 拥有另一个 Core Data 实体对象名称 Entity_Type 并将其连接到多个,以便我可以轻松获得描述。例如,这将使我能够轻松地在 UIPickerView 中使用。

  2. 我还可以看到为什么 #1 是一个陷阱,因为稍后我将需要做一些类似 switch/case 的操作来处理每种类型的特定功能。作为一个核心数据对象,我没有“id”来执行 switch 语句。另一种方法是硬编码一个枚举,但是我将如何处理描述?

  3. 也许是两者的结合?

任何类似情况的建议或经验都会有很大帮助。我尝试搜索,但我发现的只是如何找到 CD 对象的 ID,这无关紧要。

【问题讨论】:

    标签: iphone ios core-data


    【解决方案1】:

    您所说的“组合”方法的工作原理如下:

    您的 Entity_Type 带有一个字符串描述和一个 NSNumber 'enumValue' 属性。

    然后,您定义一个具有显式值的枚举类型以实现向前和向后兼容性(您不希望人们在顶部插入一个新枚举并破坏所有内容)。

    // these values must not change
    enum Foo {
        FooType1 = 1,
        FooType2 = 2
    };
    

    现在,您不想将 'enumValue' 属性作为 NSNumber 处理,因此与其使用 @dynamic 生成属性,不如定义自己的 getter/setter 来公开本机枚举值而不是NS 编号。像这样的:

    - (void)setEnumValue:(enum Foo)newValue
    {
        NSNumber *numberValue = [NSNumber numberWithInt:newValue];
        [self willChangeValueForKey:@"enumValue"];
        [self setPrimitiveValue:numberValue forKey:@"enumValue"];
        [self didChangeValueForKey:@"enumValue"];
    }
    
    - (enum Foo)enumValue
    {
        [self willAccessValueForKey:@"enumValue"];
        NSNumber *numberValue = [self primitiveValueForKey:@"enumValue"];
        [self didAccessValueForKey:@"enumValue"];
    
        // optionally validate against possible enum values, maybe handle the case
        // when you are reading a database made by a later version which has new
        // unknown-to-us values, etc.
        return (enum Foo) [numberValue intValue]
    }
    

    我已经从内存中编写了这段代码,但这是事情的一般要点。 getter/setter 与底层托管对象的 NSNumber 值对话,但您的对象本身将该属性公开为您的强类型枚举类型。

    然后您可以定义一些辅助方法来获取枚举值的关联实体。这应该只是一个带有enumValue == %@ 谓词的简单获取请求。

    您还必须小心处理未知的枚举值。您的软件的旧版本最终可能会读取包含它不知道的新枚举值的数据库。

    【讨论】:

    • 我实际上从未意识到实现自定义托管对象 getter/setter 的代码如此之多。我不介意使用 NSNumber,但困难的事情是将其他“元”数据与枚举相关联。我想硬编码函数是获得它的唯一方法。
    • 其他元数据应该只是实体上的更多属性。只要你有 enum 属性,你就可以在实体和它的枚举值之间进行映射,其他一切都照常工作。
    【解决方案2】:

    我过去使用过枚举。就像我有一个实体来表示成本,它有一个成本类型,我将其定义为枚举并作为 int 存储在核心数据中。有 4 种可能的成本类型(固定、时间、产品、旅行),根据成本类型,成本值的计算方式会有所不同。

    我认为这就是你的意思,否则我会说给我一个更坚定的例子。

    【讨论】:

    • 如果您将枚举值存储为 NSNumber 整数,请记住为每个枚举常量提供一个明确的值,该值永远不会改变以实现前向兼容性。您不希望人们在顶部插入新值并破坏一切。
    • 是的,这就是我所指的,这是一个典型的例子。唯一的问题是,除了那些成本类型整数之外,我还需要一个缺少枚举的字符串描述。因此,例如,我需要一些方法来轻松地将“kFixedCost”枚举值链接到“Fixed Cost Type”描述。
    【解决方案3】:

    我建议另外两个工具来提供帮助。

    1. 注意您可以覆盖的 NSObject“描述”方法,以提供任何内容的字符串表示。因此,如果您将 NSNumber 子类化以创建仅允许枚举值集的 NSNumber,您还可以添加“description”方法,该方法将简单地将值查找为某些描述数组中的索引。像

    2. 非常注意 NSValueTransformer!您可以创建一个从任何类型到任何类型的独立变压器(以及返回,用于双向变压器)。您可以将转换器直接附加到 .xib 中的 UI,因此当您将 NUMERICAL 值(您的枚举)设置到 UI 字段时,用户将看到 THE TRANSFORMED(字符串)值。反过来也一样。

    我没有附加代码,因为我很着急,但我很快就会做。

    上述方法是替代解决方案,但也许您可以按照 Mike Weller 建议的方式组合它们 --- 为 core-data 中的属性添加一个新的强类型枚举访问器(这将是某种 int) ,但不要使用枚举,而是使用覆盖了“描述”的 NSNumber 的子类,以及枚举访问器。

    然后为这个类定义一个转换器(转换为字符串),它在转换为字符串时将简单地返回描述,并在给出描述时执行相反的操作。

    将此转换器附加到您的 UI,瞧!

    这里描述的技术也适用于 Mac,而不仅仅是 iOS。

    【讨论】:

      猜你喜欢
      • 2019-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-06
      • 2016-07-30
      相关资源
      最近更新 更多