Search code examples
iosswiftrealm

Why can't I use private on a Realm property


I am trying to store an enum case in RealmSwift. But Realm doesn't support enums. This article suggests a cool solution. In it they prepend private to the one property in the Realm class so as to prevent it from being set or read from outside the class, and then use some getters and setters on another property to read and write to that private property.

Here is my version of that solution:

@objcMembers
class PlaylistRealmObject: Object {

    dynamic var id: String = UUID().uuidString
    dynamic var created: Date = Date()
    dynamic var title: String = ""
    private dynamic var revisionTypeRaw: String = RevisionType.noReminder.rawValue
    var revisionType: RevisionType {
        get { return RevisionType(rawValue: revisionTypeRaw)! }
        set { revisionTypeRaw = newValue.rawValue }
    }
    let reminders = List<ReminderRealmObject>()
    let cardsInPlaylist = List<CardRealmObject>()

    override static func primaryKey() -> String? {
        return "id"
    }

}

I tried to implement the solution but found that adding private to the one property was causing Realm to ignore the property on the schema.

Another article implements the same solution but without using private. If there is a way to make a Realm property private that would be the best implementation of the solution in my view.

Is there a way to make properties in a Realm class private? If not, why?


Solution

  • This is tough to answer because our project has a similar setup and it's working. So let me try to present an answer via an example of what how our code looks.

    First, the realm object. the object has an id, a name and then a visible property revisionType which is assigned via an enum (not managed by Realm) that's backed by a private revisionTypeRaw which is managed by realm.

    class PlaylistRealmObject: Object {
        enum RevisionTypeEnum: String {
            case type_a = "a"
            case type_b = "b"
        }
    
        @objc dynamic var list_id = UUID().uuidString
        @objc dynamic var list_name = ""
    
        @objc private dynamic var revisionTypeRaw: String = ""
        var revisionType: RevisionTypeEnum {
            get {
                let x = RevisionTypeEnum(rawValue: revisionTypeRaw)!
                return x
            }
            set {
                revisionTypeRaw = newValue.rawValue
            }
        }
    
        override static func primaryKey() -> String? {
            return "list_id"
        }
    }
    

    then we create a couple of playlists and store in Realm

    let newAgePlaylist = PlaylistRealmObject()
    newAgePlaylist.list_name = "New Age"
    newAgePlaylist.revisionType = .type_a
    
    let classicRockPlaylist = PlaylistRealmObject()
    classicRockPlaylist.list_name = "Classic Rock"
    classicRockPlaylist.revisionType = .type_b
    
    realm.add(newAgePlaylist)
    realm.add(classicRockPlaylist)
    

    then to check it, load in all of the playlists and print to console depending on what type of revision they are

    let playlistResults = realm.objects(PlaylistRealmObject.self)
    for playlist in playlistResults {
        let name = playlist.list_name
        if playlist.revisionType == .type_a {
            print("name: \(name) is a type_a playlist")
        } else {
            print("name: \(name) is a type_b playlist")
        }
    }