Search code examples
iosswiftuilabeluicontrol

Updating UILabel text when variable changes


I've got a UIControl class and need to do some calculation based on UIImageView location which can be moved with touchesBegan and touchesMoved (everything inside this class). Than I would like to display it as a UILabel which I've created programmatically.

class control : UIControl{
   ...
   let leftControl: UIImageView = UIImageView(image: UIImage(named: "left-control"))
   ...
   func leftValue() -> String{
       var leftValue : String = "0.0"
       leftValue = "\(leftControl.center.x)"
       return leftValue
   }
}

and my ViewController.swift

class ViewController: UIViewController {

let ctrl : Control = Control()
let leftLabel : UILabel = UILabel(frame: CGRect(x: 40, y: 300, width: 150, height: 30))

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    ctrl.frame.origin = CGPoint(x: 40, y: 400)

    leftLabel.text = "\(ctrl.leftValue())" //displays only starting value

    view.addSubview(slider)
    view.addSubview(leftLabel)
    view.addSubview(rightLabel)
}

I know that it's inside the viewDidLoad so it's not updating properly. I was wondering about scheduledTimer but don't know if it's good solution.


Solution

  • You can achieve this using protocols and delegation - in the file for your Control add this :

    protocol ControlDelegate: class {
        func controlPositionDidChange(leftValue: String)
    }
    

    And add a weak var delegate: ControlDelegate? inside Control class.

    In the file for view controller make following changes :

    class ViewController: UIViewController, ControllDelegate {
    
    let ctrl : Control = Control() 
    let leftLabel : UILabel = UILabel(frame: CGRect(x: 40, y: 300, width: 150, height: 30))
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    
        ctrl.frame.origin = CGPoint(x: 40, y: 400)
        ctrl.delegate = self
    
        leftLabel.text = "\(ctrl.leftValue())" //displays only starting value
    
        view.addSubview(slider)
        view.addSubview(leftLabel)
        view.addSubview(rightLabel) 
    }
    
    func controlPositionDidChange(leftValue: String) {
        leftLabel.text = leftValue
    }
    }
    

    Now, whenever you want to inform the delegate that your control has changed the position, simply call self.delegate?.controlPositionDidChange(self.leftValue()) in appropriate places.

    As usually, there is more in the docs. I highly suggest reading through them as delegation and protocols are widely used in CocoaTouch.