Basically, I have a custom UILabel subclass that sets the label colors based on a variable.
class MyLabel: UILabel {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
textColor = GlobalVars.mainTextColor
}
}
On my view controller I have a button that sets a white background and sets the text color variable to black:
@IBAction func btnWhite(_ sender: UIButton) {
GlobalVars.mainTextColor = UIColor.black
GlobalVars.bgColor = UIColor.white
self.view.backgroundColor = UIColor.white
self.view.setNeedsDisplay()
self.view.layoutIfNeeded()
DispatchQueue.main.async { [weak self] in
self?.view.setNeedsLayout()
self?.view.layoutIfNeeded()
}
}
Once this is clicked and the variables updated, I want the ViewController to redraw the labels, which would update their text colors. This work fine if I pop the VC and come back, but I want the display to update when the buttons is clicked. I have a bunch of labels on the view and thy are all set to myLabel class. I do not want to have to manually code changes to every label on the screen, I just want to redraw it. The UIView is not a custom class, just the default UIView that comes with a View Controller. This should be occurring on the main thread already, but I have tried adding the dispatch.main.async just in case. I expect it would not need both in the end. Image of my view controller layout here
When I click the button, the background changes to white, but the label text colors do not update, I believe that is because it is not redrawing them. There is a second button btnBlack, that toggles it the exact opposite for a light/dark mode effect.
Thoughts?
Whenever GlobalVars.mainTextColor
or GlobalVars.bgColor
values change, you have to set the colors of all your labels again.
One option is to use Notifications. You can post a notification on didSet
of your global variables and catch the notification in your MyLabel
class and update the colors.
class GlobalVars {
static let onChangeColorNotification = "onChangeColorNotification"
static var mainTextColor:UIColor? {
didSet {
NotificationCenter.default.post(Notification.init(name: Notification.Name(rawValue: onChangeColorNotification)))
}
}
}
And in your MyLabel
class
class MyLabel: UILabel {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
onChangeGlogabColor()
NotificationCenter.default.addObserver(self, selector: #selector(onChangeGlogabColor), name: NSNotification.Name(rawValue: GlobalVars.onChangeColorNotification), object: nil)
}
@objc func onChangeGlogabColor() {
textColor = GlobalVars.mainTextColor
}
}
You can do the same with all your custom classes like MyButton
or MyView
, catch the notification and update the colors.
And you don't have to call setNeedsDisplay()
or layoutIfNeeded()
.
@IBAction func btnWhite(_ sender: UIButton) {
GlobalVars.mainTextColor = UIColor.black
GlobalVars.bgColor = UIColor.white
self.view.backgroundColor = UIColor.white
}