【问题标题】:Why can't I use private on a Realm property为什么我不能在 Realm 属性上使用 private
【发布时间】:2019-07-19 13:17:05
【问题描述】:

我正在尝试在 RealmSwift 中存储一个枚举案例。但是 Realm 不支持枚举。 This article 提出了一个很酷的解决方案。在其中,他们将 private 添加到 Realm 类中的一个属性之前,以防止从类外部对其进行设置或读取,然后在另一个属性上使用一些 getter 和 setter 来读取和写入该私有属性。

这是我对该解决方案的版本:

@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"
    }

}

我尝试实现该解决方案,但发现将 private 添加到一个属性会导致 Realm 忽略架构上的属性。

Another article 实现了相同的解决方案,但不使用私有。如果有办法将 Realm 属性设为私有,那么在我看来,这将是解决方案的最佳实现。

有没有办法将 Realm 类中的属性设为私有?如果不是,为什么?

【问题讨论】:

    标签: ios swift realm


    【解决方案1】:

    这很难回答,因为我们的项目有类似的设置并且它正在运行。因此,让我尝试通过一个示例来说明我们的代码的外观。

    首先,领域对象。该对象有一个 id、一个名称,然后是一个可见的属性 revisionType,该属性是通过一个由领域管理的私有 revisionTypeRaw 支持的枚举(不由领域管理)分配的。

    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"
        }
    }
    

    然后我们创建几个播放列表并存储在 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)
    

    然后检查它,加载所有播放列表并根据它们的修订类型打印到控制台

    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")
        }
    }
    

    【讨论】:

    • 好的,@Jay,您的解决方案有效。领域浏览器隐藏了私有属性,这就是愚弄我的原因。但是,我确实注意到了以下几点:您的代码和我的代码之间的唯一区别是我使用了方便的 init(我在问题的代码中省略了它)。而这种便利性 init 正在大肆破坏。但为什么?这是另一个问题,发布在这里:stackoverflow.com/questions/57147754/…
    • 为任何发现此问答的人更新上述内容。对我来说,问题不在于便利性初始化,而是我在班级顶部使用@objcMembers。如果我删除它并在属性上添加@objc,那么一切都会按预期工作。
    • 伟大的发现@thecloud_of_unknowing!但是我想说我们不需要从类声明中删除 objcMembers - 相反,我们可以将“强制”objc 放入我们的 private var
    • @PavelVavilov 在类声明中使用@objcMembers 的问题是它需要ALL 类中的变量(动态)并尝试管理它们。我建议仅使用 @objd dynamic var .... 指定您想要单独管理的变量,因为它提供了更细粒度的控制。
    • @Jay 同意你的看法。当你有一个超过 15 个变量的类并且你想存储在领域数据库中时,我更多地考虑了这种情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 2021-07-25
    • 1970-01-01
    • 2016-09-20
    相关资源
    最近更新 更多