【问题标题】:Swift 4 - setNeedsDisplay and layoutIfNeeded not redrawing UILabel on self.UIViewSwift 4 - setNeedsDisplay 和 layoutIfNeeded 不在 self.UIView 上重绘 UILabel
【发布时间】:2018-01-29 05:54:52
【问题描述】:

基本上,我有一个自定义 UILabel 子类,它根据变量设置标签颜色。

class MyLabel: UILabel {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        textColor = GlobalVars.mainTextColor
    }
}

在我的视图控制器上,我有一个设置白色背景并将文本颜色变量设置为黑色的按钮:

@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()
        }
    }

单击此按钮并更新变量后,我希望 ViewController 重新绘制标签,这将更新它们的文本颜色。如果我弹出 VC 并返回,这可以正常工作,但我希望在单击按钮时更新显示。我在视图上有一堆标签,它们都设置为 myLabel 类。我不想手动更改屏幕上的每个标签,我只想重新绘制它。 UIView 不是自定义类,只是 View Controller 附带的默认 UIView。这应该已经在主线程上发生了,但我尝试添加 dispatch.main.async 以防万一。我希望它最终不需要两者。 Image of my view controller layout here

当我单击按钮时,背景变为白色,但标签文本颜色没有更新,我相信这是因为它没有重绘它们。还有第二个按钮 btnBlack,可将其切换为完全相反的亮/暗模式效果。

想法?

【问题讨论】:

  • 我看不到您在 btnWhite(:) 方法中设置标签文本颜色??并设置您没有调用setNeedsDisplay()layoutIfNeeded() 的视图背景颜色或文本颜色。
  • 标签文本颜色在创建标签时通过类 init 设置。这使我可以在一个地方“GlobalVars.mainTextColor”更改颜色,并且使用该类加载的每个标签都会获得该颜色文本。我知道我可以为所有标签手动编码 eachLabel.textColor = GlobalVars.mainTextColor,但有两个原因这不起作用。 1. 有很多标签,我不想每一个都编码。 2. 作为这个 VC 的父级的根 VC 也需要重新加载它的所有标签。这么多编码。我宁愿强制重绘并让类 init 完成工作。

标签: swift uilabel redraw setneedsdisplay


【解决方案1】:

每当GlobalVars.mainTextColorGlobalVars.bgColor 值发生变化时,您必须重新设置所有标签的颜色。

一种选择是使用通知。您可以在您的全局变量的didSet 上发布通知,并在您的MyLabel 类中捕获通知并更新颜色。

class GlobalVars {
    static let onChangeColorNotification = "onChangeColorNotification"
    static var mainTextColor:UIColor? {
        didSet {
            NotificationCenter.default.post(Notification.init(name: Notification.Name(rawValue: onChangeColorNotification)))
        }
    }
}

在你的MyLabel 课堂上

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

您可以对所有自定义类(如 MyButtonMyView)执行相同操作,捕获通知并更新颜色。

而且您不必致电setNeedsDisplay()layoutIfNeeded()

@IBAction func btnWhite(_ sender: UIButton) {
    GlobalVars.mainTextColor = UIColor.black
    GlobalVars.bgColor = UIColor.white
    self.view.backgroundColor = UIColor.white        
}

【讨论】:

  • 这是个好主意,现在试试,我会告诉你的。
【解决方案2】:

您必须更改按钮单击方法中的 TextColor

@IBAction func btnWhite(_ sender: UIButton) {
     myCustomLabel.textColor = UIColor.blue
} 

并且不需要调用下面提到的方法

self.view.setNeedsDisplay()
self.view.layoutIfNeeded()

注意:没有其他方法可以改变 UIlabel TextColor

【讨论】:

  • 标签文本颜色在创建标签时通过类 init 设置。这使我可以在一个地方“GlobalVars.mainTextColor”更改颜色,并且使用该类加载的每个标签都会获得该颜色文本。我知道我可以为所有标签手动编码 eachLabel.textColor = GlobalVars.mainTextColor,但有两个原因这不起作用。 1. 有很多标签,我不想每一个都编码。 2. 作为这个 VC 的父级的根 VC 也需要重新加载它的所有标签。这么多编码。我宁愿强制重绘并让类 init 完成工作。
  • 类 init 在创建标签时设置颜色,因此我不想手动更改标签颜色,我只想让屏幕重新绘制所有标签,这将设置它们的新颜色。 .FAR 更少的编码和维护,如果我添加/更改标签,我只需要确保他们的类已设置。
【解决方案3】:

Bilal 的回答是正确的。有时需要一种完全不同的方法。感谢您的新鲜眼睛,这是最终代码。

添加下面的代码并将所有标签设置为此“MyLabel”类。然后,只要 GlobalVars.mainTextColor 变量发生更改,标签就会更新其文本颜色。这可以适用于 UIButtons 或当 var 更改时需要更新的任何属性。这会在加载的任何 VC 上使用此类更新任何标签。这也解决了我的根 VC 标签也需要更新的问题,因为它们也已经用原始颜色绘制,非常光滑!

class MyLabel: UILabel {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        textColor = GlobalVars.mainTextColor
        NotificationCenter.default.addObserver(self, selector: #selector(onChangeGlobalColor), name: NSNotification.Name(rawValue: "onChangeColorNotification"), object: nil)
    }
    @objc func onChangeGlobalColor() {
        textColor = GlobalVars.mainTextColor
    }
}

struct GlobalVars {
    static var mainTextColor:UIColor = UIColor() {
        didSet {
            NotificationCenter.default.post(Notification.init(name: Notification.Name(rawValue: "onChangeColorNotification")))
        }
    }

@IBAction func btnWhite(_ sender: UIButton) {
        GlobalVars.mainTextColor = UIColor.black
        self.view.backgroundColor = UIColor.white
    }
@IBAction func btnBlack(_ sender: UIButton) {
        GlobalVars.mainTextColor = UIColor.white
        self.view.backgroundColor = UIColor.black
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-17
    • 2023-04-08
    相关资源
    最近更新 更多