Change text of label whenever UserDefaults key value changes

I have an app where there are 2 views, one with a UILabel and another with a UITextField. I would like it so the moment you are done editing the Text Field, the label changes to the TF's value. The text field stores its value in a UserDefaults and when my Label's View loads, it shows the value of the UD key on the label. Again, I would like it so the moment you are done editing the Text Field, the label changes to the TF's value.








Below is my Label's View's Controller

Code Block Swift
struct myStruct {
    static var money = 0.00
}
import UIKit
class ViewController: UIViewController {
    @IBOutlet weak var moneyLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        let ud = UserDefaults.standard
        myStruct.money = ud.double(forKey: "Money")
        moneyLabel.text = String(ud.double(forKey: "Money"))
        
    }
}




My TextField's View's Controller

Code Block swift
import UIKit
class AddMoneyViewController: UIViewController {
    
    let userDefaults = UserDefaults.standard
    
    
    @IBOutlet weak var TextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
       
    
    }
    
    @IBAction func TFEditingDidEnd(_ sender: Any) {
        userDefaults.set(TextField.text, forKey: "Money")
        let moneyAtPoint1 = userDefaults.double(forKey: "Money")
        print(moneyAtPoint1)
    
    }
    
}




Answered by OOPer in 617863022
UserDefaults is a KVO compliant class and you can observe on its member "Money" as follows.
Code Block
extension UserDefaults {
    //Dummy definition to make KeyPath available
    @NSManaged var Money: Double
}
class ViewController: UIViewController {
    @IBOutlet weak var moneyLabel: UILabel!
    var udObservation: NSKeyValueObservation?
    override func viewDidLoad() {
        super.viewDidLoad()
        let ud = UserDefaults.standard
        moneyLabel.text = String(ud.double(forKey: "Money"))
        udObservation = ud.observe(\.Money, options: .new) {ud, change in
            if let newValue = change.newValue {
                self.moneyLabel.text = String(newValue)
            }
        }
    }
}


If you want to watch on Double value, you need to set a value of Double, not String.
Code Block
import UIKit
class AddMoneyViewController: UIViewController {
    let userDefaults = UserDefaults.standard
    @IBOutlet weak var TextField: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    @IBAction func TFEditingDidEnd(_ sender: Any) {
        //You need to set `Double` value, not `String`
        userDefaults.set(Double(TextField.text ?? "") ?? 0, forKey: "Money")
        let moneyAtPoint1 = userDefaults.double(forKey: "Money")
        print(moneyAtPoint1)
    }
}

(This is not a critical issue about your app's behavior, but you should better use Capitalized id only for types in Swift. TextField or TFEditingDidEnd is not appropriate for property name or method name.)

One more, you should better consider using NumberFormatter to convert Double and the text of the text field.
Accepted Answer
UserDefaults is a KVO compliant class and you can observe on its member "Money" as follows.
Code Block
extension UserDefaults {
    //Dummy definition to make KeyPath available
    @NSManaged var Money: Double
}
class ViewController: UIViewController {
    @IBOutlet weak var moneyLabel: UILabel!
    var udObservation: NSKeyValueObservation?
    override func viewDidLoad() {
        super.viewDidLoad()
        let ud = UserDefaults.standard
        moneyLabel.text = String(ud.double(forKey: "Money"))
        udObservation = ud.observe(\.Money, options: .new) {ud, change in
            if let newValue = change.newValue {
                self.moneyLabel.text = String(newValue)
            }
        }
    }
}


If you want to watch on Double value, you need to set a value of Double, not String.
Code Block
import UIKit
class AddMoneyViewController: UIViewController {
    let userDefaults = UserDefaults.standard
    @IBOutlet weak var TextField: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    @IBAction func TFEditingDidEnd(_ sender: Any) {
        //You need to set `Double` value, not `String`
        userDefaults.set(Double(TextField.text ?? "") ?? 0, forKey: "Money")
        let moneyAtPoint1 = userDefaults.double(forKey: "Money")
        print(moneyAtPoint1)
    }
}

(This is not a critical issue about your app's behavior, but you should better use Capitalized id only for types in Swift. TextField or TFEditingDidEnd is not appropriate for property name or method name.)

One more, you should better consider using NumberFormatter to convert Double and the text of the text field.
My question is I want it so whenever the value of "Money" changes, My label updates!

My problem is my Label is on a different view then the TextField
Change text of label whenever UserDefaults key value changes
 
 
Q