Ilir V. Gruda Ilir V. Gruda - 2 months ago 37
iOS Question

Execute a method when a variable value changes in Swift

I need to execute a method when a variable value changes.

More specifically I have a singleton class which has a shared variable called

labelChange
. Values of this variable are taken from another class called
Model
. Moreover I have two VC classes one of them has a button and a label and the second only a button

When the button in the first VC class is pressed I am updating the label by calling this method:

func updateLable(){
self.label.text = SharingManager.sharedInstance.labelChange
}


But I want to call the same method whenever the value of the
labelChange
is changed. So in button click I will only update the
labelChange
value and when this thing happen I want to update the label with the new value of the
labelChange
. Also in the Second VC I am being able to update the
labelChange
value but I am not being able to update the label when this value is changed.

Maybe properties are the solution but can anyone show me how to do so.

Edited second time:

Singleton Class:

class SharingManager {
func updateLable(){
println(labelChange)
ViewController().label.text = SharingManager.sharedInstance.labelChange
}
var labelChange: String = Model().callElements() {
willSet {
updateLable()
}
}
static let sharedInstance = SharingManager()
}


First VC:

class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
@IBAction func Button(sender: UIButton) {
SViewController().updateMessageAndDismiss()
}
}


Second VC:

func updateMessageAndDismiss() {
SharingManager.sharedInstance.labelChange = modelFromS.callElements()
self.dismissViewControllerAnimated(true, completion: nil)
}
@IBAction func b2(sender: UIButton) {
updateMessageAndDismiss()
}


I have made some improvements but I need to reference a label from the first VC class in singleton. Therefore I will update that label of VC in singleton.

The problem is that when I am printing the value of
labelChange
the value is being updated and everything is fine. But when I am trying to update that value on label from singleton I am having an error saying:


unexpectedly found nil while unwrapping an Optional value


and the error is pointing in 4th line of singleton class.

Answer

You can simply use a property observer for the variable, labelChange, and call the function that you want to call inside didSet (or willSet if you want to call it before it has been set):

class SharingManager {
    var labelChange: String = Model().callElements() {
        didSet {
            updateLable()
        }
    }
    static let sharedInstance = SharingManager()
}

This is explained in Property Observers.

I'm not sure why this didn't work when you tried it, but if you are having trouble because the function you are trying to call (updateLable) is in a different class, you could add a variable in the SharingManager class to store the function to call when didSet has been called, which you would set to updateLable in this case.


Edited:

So if you want to edit a label from the ViewController, you would want to have that updateLable() function in the ViewController class to update the label, but store that function in the singleton class so it can know which function to call:

class SharingManager {
    static let sharedInstance = SharingManager()
    var updateLable: (() -> Void)?
    var labelChange: String = Model().callElements() {
        didSet {
            updateLable?()
        }
    }
}

and then set it in whichever class that you have the function that you want to be called, like (assuming updateLable is the function that you want to call):

SharingManager.sharedInstance.updateLable = updateLable

Of course, you will want to make sure that the view controller that is responsible for that function still exists, so the singleton class can call the function.

If you need to call different functions depending on which view controller is visible, you might want to consider Key-Value Observing to get notifications whenever the value for certain variables change.

Also, you never want to initialize a view controller like that and then immediately set the IBOutlets of the view controller, since IBOutlets don't get initialized until the its view actually get loaded. You need to use an existing view controller object in some way.

Hope this helps.