简体   繁体   中英

How to update swift NSObject model having same property in other controllers using property observer?

I was going through Apple documentation and some tutorials where I learnt we can set observer which will be called if object if modified. But I have few doubts in my mind.

Here is a summary where a model is notified about the property changes:

在此处输入图片说明

Suppose there are 3 view controllers and they show listing of Foo models. Foo model has properties called id and title . My question is, is it feasible to get notified in others controllers that Foo model is modified which is having id 10 for example. Is that possible only if same instance of model is shared between 3 controllers, or we can achieve it although instances are different?

I am looking for a concrete solution, where a user like a feed (similar as Facebook) in one screen and if a feed with same id is in other controller, that controller should be notified that this feed is modified, refresh its UI. I have attached an image for clear idea.

在此处输入图片说明

I do not wish to go with delegate or notification pattern as it might create chaos, rather observer pattern will be more proper solution.

Here is an example of how you can achieve this.

Feed Model:

class Feed: NSObject {
    var id: String
    @objc dynamic var isLiked = false

    init(id: String) {
        self.id = id
    }
}

Any property that you want to observe, mark it @objc dynamic , ie isLiked in Feed model.

class ListVC: UIViewController {
    let feed = Feed(id: "1")
    var observer: NSKeyValueObservation?

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func openDetailVC(_ sender: UIButton) {
        if let detailVC = self.storyboard?.instantiateViewController(withIdentifier: "DetailVC") as? DetailVC {
            self.observer = detailVC.feed.observe(\.isLiked, options: [.new], changeHandler: { (feed, change) in
                if let newValue = change.newValue {
                    print(newValue)
                    //Reload the UI here...
                }
            })
            self.navigationController?.pushViewController(detailVC, animated: true)
        }
    }
}

Next there is a ListVC that has a feed property.

Add an observer to feed in viewDidLoad() . Specify the property that you want to observe in feed ie isLiked . The closure in the observer will be called every time there is a change in isLiked property.

Now, DetailVC will be.

class DetailVC: UIViewController {
    let feed = Feed(id: "1")

    @IBAction func likeButtonPressed(_ sender: UIButton) {
        self.feed.isLiked = !self.feed.isLiked
    }
}

In the above code, I'm changing the value of isLiked property in feed whenever likeButton is pressed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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