Adrian
Adrian

Reputation: 16725

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?

Upvotes: 0

Views: 140

Answers (2)

Nirav D
Nirav D

Reputation: 72440

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.
    }
}

Upvotes: 2

tonik12
tonik12

Reputation: 613

I guess you should do:

func updateLabel(timeRemaining: Int) -> String {
    let formattedTime = formatTimeInSeconds(timeRemaining)
    delegate.updateLabel(formattedTime)
    return formattedTime
}

And in the ItemViewController you should declare that the class follows the delegate and implement the declared method. Something like:

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

}

Upvotes: 0

Related Questions