Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift how to tell when a variable changed in a shared instance

Tags:

swift

I have a variable in a singleton pattern that is used/referenced through out the app.

I have a mainVC that has a custom view in it that sets a variable. I want the view controller that is presented in the navigation controller to be notified when this variable changes.

For example:

in my mainVC it has an embedded navigation controller, which I push View1. On the mainVC toolbar, there is a textfield that the user can enter values. When this values changes, I would like to have View1 to know it has changed. View1 can be any view that is currently presented.

like image 351
Arcadian Avatar asked Nov 17 '17 19:11

Arcadian


3 Answers

I would create a didSet value observer on that variable. Then when any ViewController willappear, set the delegate to self. And track the changes of that variable on the ViewController.

Each ViewController should do:

class ViewController: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    
        Singleton.shared.delegate = self
    }
}

extension ViewController: SingletonDelegate {
    func variableDidChange(newVariableValue value: Int) {
    //here u get value if changed
    }
}

And the Singleton with your variable and protocol

protocol SingletonDelegate: class {
    func variableDidChange(newVariableValue value: Int)
}

class Singleton {

    var variable:Int = 0 {
       didSet {
          delegate?.variableDidChange(newVariableValue: variable)
       }
    }

    private init() {}
    weak var delegate: SingletonDelegate?

    static let shared = Singleton()
}

PD: notice this way only the top ViewController in the navigation will handle the newValue event.

like image 53
alegelos Avatar answered Nov 10 '22 13:11

alegelos


I have used this pattern a few times and I prefer to use NotificationCenter.

In your Singleton class you need to use Post method every time the value changes , And in your viewcontroller you would add the observer to reflect or react to the change.

There are multiple ways to tackle this. And there are plenty of great tutorials out there for the same.

like image 32
OverD Avatar answered Nov 10 '22 12:11

OverD


I wanted to add to @matt 's comment, KVO is one way to go about your solution, and from your question I think it would be the best way. You can use the "normal" KVO which is what I implement when using it that @matt linked to.

BUT, I did find a new way that KVO can be set up that I didn't know before so I wanted to share it:

var testString: String = "Hello World" {
    //After setting 🔥
    didSet {
      // Code you want to execute after a new value is set
    }

    //Prior to setting 🐶
    willSet {
      // Code you want to execute right before setting a new value
    }
}

I seen this while reading this article: KVO and Lazy Stored Properties

like image 31
Jacob Boyd Avatar answered Nov 10 '22 13:11

Jacob Boyd