Realm-cocoa: Is it possible to have a property as an Enum?

Created on 29 Jan 2016  路  4Comments  路  Source: realm/realm-cocoa

enum BillState {
    case Overdue
    case Closed
    case Open
    case Future

    static func stateFromString(stateString: String) -> BillState? {
        switch stateString {
        case "overdue":
            return .Overdue
        case "open":
            return .Open
        case "closed":
            return .Closed
        case "future":
            return .Future
        default:
            return nil
        }
    }
}

class Bill: Object {
    dynamic var state: BillState
    dynamic var dueDate: NSDate
    dynamic var totalCumulative: Int

    required init() {
        super.init()
    }

    convenience init(billJSON: JSON) {
        self.init()
        ...
    }
}

Currently I cannot do that since dynamic var state: BillState gives me the error Property cannot be marked dynamic because its type cannot be represented in Objective-C.

Is there any other way for this to work with Realm?

Thanks!

T-Help

Most helpful comment

Hi @mikailcf, this is how we recommend you do this. The general pattern looks like this:

class Bill: Object {
  private dynamic var rawState = -1
  public var state: BillState {
    get {
      return BillState(rawValue: rawState)!
    }
    set {
      rawState = newValue.rawValue
    }
  }

  override static func ignoredProperties() -> [String] {
    return ["state"]
  }
}

We're tracking adding better support for this in #921.

All 4 comments

Well, for now I went with this solution:

enum BillState: Int {
    case Overdue  = 0
    case Closed   = 1
    case Open     = 2
    case Future   = 3

    static func stateFromString(stateString: String) -> BillState? {
        switch stateString {
        case "overdue":
            return .Overdue
        case "open":
            return .Open
        case "closed":
            return .Closed
        case "future":
            return .Future
        default:
            return nil
        }
    }
}

class Bill: Object {
    private dynamic var mappedState: Int = -1
    private dynamic var mappedDueDate: NSDate? = nil
    private dynamic var mappedTotalCumulative: Int = 0

    var state: BillState? {
        return BillState(rawValue: self.mappedState)
    }

    var dueDate: NSDate? {
        return self.mappedDueDate
    }

    var totalCumulative: Int {
        return self.mappedTotalCumulative
    }

    convenience init(billJSON: JSON) {
        self.init()
        // getting the value from a JSON with SwiftyJSON as an example
        guard let state = BillState.stateFromString(billJSON["state"].stringValue) else {
            return
        }

        self.mappedState = state.rawValue
        ...
    }
}

With that I have a nice public interface, while also, privately, having what Realm needs to do its magic.

Hi @mikailcf, this is how we recommend you do this. The general pattern looks like this:

class Bill: Object {
  private dynamic var rawState = -1
  public var state: BillState {
    get {
      return BillState(rawValue: rawState)!
    }
    set {
      rawState = newValue.rawValue
    }
  }

  override static func ignoredProperties() -> [String] {
    return ["state"]
  }
}

We're tracking adding better support for this in #921.

I see, of course! Thank you!
And it's great to know you're adding support for it too!

Alright, so please subscribe to #921 to get updates on our progress on that.

Was this page helpful?
0 / 5 - 0 ratings