【问题标题】: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 中是否可行,或者是否已经有功能请求?

【问题讨论】:

    标签: ios enums 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
        }
      }
    }
    

    【讨论】:

    • 如果您可以将此示例添加到您的官方示例中,那就太好了。
    • 这不是很好。你为什么不能这样做?:stackoverflow.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? 
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-10
            • 1970-01-01
            • 1970-01-01
            • 2017-11-13
            相关资源
            最近更新 更多