使用枚举作为领域模型的属性

Posted

技术标签:

【中文标题】使用枚举作为领域模型的属性【英文标题】:Using enum as property of Realm model 【发布时间】:2015-05-21 07:22:37 【问题描述】:

是否可以将枚举用作我的模型的属性?我目前有这样的课程:

class Checkin: RLMObject 
  dynamic var id: Int = 0
  dynamic var kind: String = "checked_in"
  var kindEnum: Kind = .CheckedIn 
    willSet  self.kind = newValue.rawValue 
  

  enum Kind: String 
    case CheckedIn = "checked_in"
    case EnRoute = "en_route"
    case DroppedOff = "dropped_off"
  
  ....

它工作正常,但我希望能够将 kind 属性设为 Enum,并让 Realm 在将对象保存到商店时自动调用该属性上的 .rawValue。这在 Realm 中是否可行,或者是否已经有功能请求?

【问题讨论】:

【参考方案1】:

对于这种情况,您应该覆盖 kindEnum 的 setter 和 getter:

enum Kind: String 
  case CheckedIn
  case EnRoute
  case DroppedOff


class Checkin: Object 
  @objc dynamic var id = 0
  var kind = Kind.CheckedIn.rawValue
  var kindEnum: Kind 
    get 
      return Kind(rawValue: kind)!
    
    set 
      kind = newValue.rawValue
    
  

【讨论】:

如果您可以将此示例添加到您的官方示例中,那就太好了。 这不是很好。你为什么不能这样做?:***.com/questions/26900302/…(Martin Krenek 的回答)? 您也可以直接将 @objc 枚举与 Realm 一起使用,但这不适用于具有 String 关联值的 Swift 枚举。 在没有来自 Realm 的“官方”支持(如果可能的话)的情况下,这非常有用。谢谢。 您可以将 kind 变量设置为私有,因此您只能使用 kindEnum 更改其值。【参考方案2】:

我进一步完善了这个模型。

enum Thing: String 
    case Thing1
    case Thing2
    case Thing3

然后在我的 Realm 类对象中:

class myClass : Object 
    private dynamic var privateThing = Thing.Thing1.rawValue
    var thing: Thing 
        get  return Thing(rawValue: privateThing)! 
        set  privateThing = newValue.rawValue 
    

这让我们可以写

myClassInstance.thing = .Thing1

(将“Thing1”存储到 privateThing),但阻止输入

myClassInstance.privateThing = "Thing4"

这不是一个有效值,因此可以保持数据完整性。

【讨论】:

更新:我已经编辑了我的原始代码,因为 = "Thing1" 等是多余的,因为 Swift 对其 rawValue 使用与大小写等效的字符串文字,这更好,我们可以使用rawValue 设置更可靠和更清洁的默认值。 :-) 感谢您的补充,我真的很喜欢这个答案。 +1【参考方案3】:

由于 Realm 支持 Objective-C 枚举并且它们可以由 Int 表示,你可以使用这个:

class Checkin: Object 
  dynamic var id: Int = 0
  dynamic var kind: Kind = .checkedIn

  @objc enum Kind: Int 
    case checkedIn
    case enRoute
    case droppedOff
  
  ....

如果您需要解析 String 或从 String 解析,您可以为 KindtoString 函数使用自定义初始化程序。

GitHub有关于这个的讨论

这适用于 Swift 3.0 和 Realm 2.0.2

【讨论】:

如果你有一个Int 枚举很好的解决方案,但它看不到它如何与String 一起工作。 Kind 被转换为不支持自定义初始化程序或存储属性的 Objective-C 枚举.. ? 确实,除了Int,我还没有找到适用于任何类型的解决方案 感谢您提供此信息。我更改了枚举以符合 int。如果您需要一个字符串值,您可以在枚举中创建自己的计算属性,并为不同的情况返回正确的值。 请注意,任何涉及 Int 枚举的迁移都需要分配原始值:obj["propertyName"] = Kind.checkedIn.rawValue【参考方案4】:

Diogo T 的解决方案在最近更新 RealmSwift 之前有效。最终,我们现在必须遵守 RealmEnum 协议才能成为 Realm Object 的托管属性。

@objc enum MyEnum: Int, RealmEnum 
    ...

或者在下面的某个地方添加:

extension MyEnum: RealmEnum  

RealmSwift documentation for it

【讨论】:

【参考方案5】:

RealmEnumRealmOptional 为例

@objc enum MyEnum: Int, RealmEnum 
    case first
    case second


final class MyEntry: Object 
    //It should be let
    let someVariable = RealmOptional<CRUD>()


//using
myEntry.someVariable.value = MyEnum.first

【讨论】:

【参考方案6】:

避免强制展开的替代解决方案 得到返回东西(rawValue:privateThing)!

enum Kind: String, CaseIterable 
      case CheckedIn
      case EnRoute
      case DroppedOff
    

    @objc dynamic var kindRaw = Kind.CheckedIn.rawValue
    var kind: Kind 
        get 
            for kind in Kind.allCases where kindRaw == kind.rawValue 
                return kind
            
            return .CheckedIn //default
        
        set 
            kindRaw = newValue.rawValue
        
    

【讨论】:

【参考方案7】:

Realm 10.0.0 引入了PersistableEnum 协议,无需任何第三方扩展即可轻松持久化枚举值。

enum TaskStatusEnum: String, PersistableEnum 
    case notStarted
    case inProgress
    case complete

// To use the enum:
class Task: Object 
    // Required enum property
    @Persisted var status = TaskStatusEnum.notStarted 
    // Optional enum property
    @Persisted var optionalTaskStatusEnumProperty: TaskStatusEnum? 

【讨论】:

以上是关于使用枚举作为领域模型的属性的主要内容,如果未能解决你的问题,请参考以下文章

[第五章]领域模型

货币交易领域模型

UML和模式应用5:细化阶段--如何创建领域模型

译文一个设计精良的领域驱动模型的五个特征

DDD领域模型企业级系统

NLP领域的ImageNet时代到来:词嵌入「已死」,语言模型当立