简体   繁体   English

斯威夫特3:单身人士的财产观察员

[英]Swift 3: Property observer for singleton

I wonder if there's any way to observe singleton class for changes in ony of its property 我想知道是否有任何方法可以观察单例类的属性ony的变化

In my case, with Realm I have something like this 在我的情况下,使用Realm我有类似的东西

class User: Object {
   dynamic var name:String = ""
   dynamic var email:String = ""
   dynamic var id:String = ""
   dynamic var picURL:String = ""
   dynamic var pic:Data = Data()

    static let currentUser = User()
    {
        didSet
        {
            try! realm.write {
                realm.add(currentUser, update: true)
            }
    }
  }
}

What I want to achieve is I want to have only one user object in my app, and anytime any of its properties gets modified, I would like to save it to Realm. 我想要实现的是我想在我的应用程序中只有一个用户对象,并且任何时候任何属性都被修改,我想将它保存到Realm。

However, the example above shows error that 但是,上面的示例显示错误

'let' declarations cannot be observing properties 'let'声明不能观察属性

How would you approach it? 你会怎么做? Do you think my idea with having Realm object singleton and updating it anytime some property changes is a good idea? 您是否认为我的想法是让Realm对象单例并随时更新它的某些属性更改是一个好主意?

I wonder if it actually makes any sense to have a singleton object of class that is persisted by Realm. 我想知道拥有Realm持久化的类的单例对象是否真的有意义。

Well, if you just have one user, you should put this observer in each variable, instead of in the let user . 好吧,如果你只有一个用户,你应该把这个观察者放在每个变量中,而不是放在let用户中 And there you can call a method for user update. 在那里你可以调用一种方法进行用户更新。

dynamic var name: String {
    didSet{
        User.updateOnRealm()//create this method
    }
}

To write the update method, you'll have to write something like this 要编写更新方法,您必须编写类似这样的内容

class func updateOnRealm() {
    //update code here
}

It's not possible to have a blanket observer for a single Realm Object at the moment, however there's an issue tracking it in the Realm GitHub and I believe it's being prioritized at the moment. 目前不可能为单个Realm Object配备一个单独的观察者,但是在Realm GitHub中跟踪它一个问题 ,我相信它现在被优先考虑。

Alcivanio is correct in that you'll need to manually trigger an update event to ensure the changes are persisted to Realm. Alcivanio是正确的,因为您需要手动触发更新事件以确保更改持久保存到Realm。 That being said, because Realm controls the accessors in persisted objects, didSet isn't guaranteed to be called once an object has been saved to Realm. 话虽如此,因为Realm控制持久化对象中的访问器, didSet一旦将对象保存到Realm,就不能保证调用didSet For simplicity reasons, I'd recommend using a closure to update the user object. 为简单起见,我建议使用闭包来更新用户对象。

Updated Answer: If your singleton is a Realm Object , you can't modify its properties outside of a write transaction. 更新的答案:如果您的单例是一个领域Object ,则无法在写入事务之外修改其属性。 Like I wrote below, the easiest thing to do would be to be to have an update closure that managed the Realm write transaction, and you simply update the properties of your Singleton object inside it. 就像我在下面写的那样,最简单的方法是拥有一个管理Realm写事务的update闭包,并且只需更新其中的Singleton对象的属性。

As you've also seen, you can't use didSet with a property defined with let , so it might be best to drop back to Objective-C conventions and use an internal instance variable. 正如你也看到了,你不能使用didSet与定义的属性let ,所以它可能是最好回落到Objective-C的约定,并使用内部的实例变量。

So all up, maybe consider doing this: 所以一切,也许考虑这样做:

fileprivate var _current: User? = nil

class User: Object {
    dynamic var name:String = ""
    dynamic var email:String = ""
    dynamic var id:String = ""
    dynamic var picURL:String = ""
    dynamic var pic:Data = Data()

    static var current: User
    {
        if _current == nil {
            let realm = try! Realm()

            // Query for an existing user
            _current = realm.objects(User.self).first

            // Create a new user if it didn't exist in Realm
            if _current == nil {
                 _current = User()
                 try! realm.write { realm.add(_current) }
            }
        }
        return _current
    }

    public func update(_ block: (() -> Void)) {
        let realm = try! Realm()
        try! realm.write(block)
    }
}

let user = User.current
user.update {
    user.name = "DCDC"
}

Based on what you wrote : 根据你所写的内容:

What I want to achieve is I want to have only one user object in my app, and anytime any of its properties gets modified, I would like to save it to Realm. 我想要实现的是我想在我的应用程序中只有一个用户对象,并且任何时候任何属性都被修改,我想将它保存到Realm。

I would suggest this solution: 我会建议这个解决方案:

  1. Create a class User which does not use the Singleton pattern. 创建一个不使用Singleton模式的class User

  2. Create a class UserManager which does conform to the Singleton pattern 创建一个符合Singleton模式的class UserManager

  3. Create custom setter methods for A User. A User创建自定义setter方法。 In these setters you can then change the users properties WITH or WITHOUT writing to the database. 在这些setter中,您可以更改用户属性WITH或WITHOUT写入数据库。 You can also check the use INPUT (set the name to lowercase etc.). 您还可以检查使用INPUT(将名称设置为小写等)。

With this approach you can easily test your User class, extend it, subclass and reuse. 使用这种方法,您可以轻松地测试您的User类,扩展它,子类和重用。

If you need code snippets comment below =). 如果您需要以下代码片段评论=)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM