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
, i.e. 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
i.e. 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.