Adrian Adrian - 2 months ago 7
iOS Question

Setting label text on a UIViewController from a Non-UIViewController Class

I have a

UIViewController
and I'm refactoring it and I've bumped into a situation where I need to update it from another class. I know I need to use the delegate pattern, but I'm having a tough time finding an example that fits my situation (which I think it dirt simple).

ItemViewController
has a
Timer
class that's instantiated. I'm trying to update an
ItemViewController
label from the
Timer
class.

On
Timer
, I've done the following:

weak var delegate: TimerDelegate? // weak to avoid a retain cycle

func updateLabel(timeRemaining: Int) -> String {
return formatTimeInSeconds(timeRemaining) // another method w/in Timer
}


I declare the
protocol
at the bottom of the
Timer
class

protocol TimerDelegate: class {
func updateLabel(timeString: String) -> String
}


On
ItemViewController
I have the following property declared:

@IBOutlet weak var timeValueLabel: UILabel?


I set it as a delegate of
Timer
in
viewDidLoad
as follows:

timer.delegate = self


What I'm trying to make happen is when
updateLabel
is called on
Timer
, I'd like to update
timeValueLabel.text
on
ItemViewController
. This is where I'm stuck...what next?

Answer

If your Timer class assign from any where and you need to change the text of label you can use singleton object for that, create one singleton object with your Timer class then use that object to set delegate like this way.

class Timer {
    static let sharedInstance = Timer()
    weak var delegate: TimerDelegate?

    //Now use this delegate to call method.
    func updateLabel(timeRemaining: Int) -> String {
        delegate?.updateLabel(formatTimeInSeconds(timeRemaining) 
        return formatTimeInSeconds(timeRemaining) 
    }         
}

Now you need to just set this delegate in your ItemViewController like this.

class ItemViewController: UIViewController, TimerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        Timer.sharedInstance.delegate = self
    }

    func updateLabel(timeString: String) -> String
        self.label.text = timeString
        return "" //return string that you want.
    }
}