UIView:appearance() 代理是如何工作的?
UIView: how does the appearance() proxy work?
我创建了一个简单的自定义 UIView
:
final class TestView: UIView {
var testColor: UIColor = .white {
didSet {
backgroundColor = testColor
}
}
}
然后我在我的视图控制器中写了这个:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var testView: TestView!
@IBOutlet weak var testView2: TestView!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
TestView.appearance().testColor = .red
}
}
}
通过这样做,我得到一个错误:
你能帮我理解这里出了什么问题以及如何为任何自定义 UIView
实施 UIAppearance
代理吗?
感谢您的帮助
您需要使 属性 @objc
和 dynamic
:
final class TestView: UIView {
@objc dynamic var testColor: UIColor? = .white {
didSet {
backgroundColor = testColor
}
}
}
值得注意:UIAppearance
代理 不会 影响已经属于视图层次结构的视图。
因此,在您的示例中,将 @objc dynamic
添加到 属性 将消除崩溃,但您将 看不到 两次 @IBOutlet
次浏览。
如果您将其作为 viewDidLoad()
的一部分调用(而不是 DispatchQueue.main.asyncAfter
):
override func viewDidLoad() {
super.viewDidLoad()
TestView.appearance().testColor = .red
}
两个 @IBOutlet
视图 将 获得红色背景。
或者,如果您向层次结构添加新视图,它将获得红色背景:
class AppearanceTestViewController: UIViewController {
@IBOutlet weak var testView: TestView!
@IBOutlet weak var testView2: TestView!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
TestView.appearance().testColor = .red
self.addAnotherTestView()
}
}
func addAnotherTestView() -> Void {
let v = TestView()
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
NSLayoutConstraint.activate([
v.widthAnchor.constraint(equalToConstant: 240.0),
v.heightAnchor.constraint(equalTo: v.widthAnchor),
v.centerXAnchor.constraint(equalTo: view.centerXAnchor),
v.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
// this newly added view WILL have a red background
}
}
我创建了一个简单的自定义 UIView
:
final class TestView: UIView {
var testColor: UIColor = .white {
didSet {
backgroundColor = testColor
}
}
}
然后我在我的视图控制器中写了这个:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var testView: TestView!
@IBOutlet weak var testView2: TestView!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
TestView.appearance().testColor = .red
}
}
}
通过这样做,我得到一个错误:
你能帮我理解这里出了什么问题以及如何为任何自定义 UIView
实施 UIAppearance
代理吗?
感谢您的帮助
您需要使 属性 @objc
和 dynamic
:
final class TestView: UIView {
@objc dynamic var testColor: UIColor? = .white {
didSet {
backgroundColor = testColor
}
}
}
值得注意:UIAppearance
代理 不会 影响已经属于视图层次结构的视图。
因此,在您的示例中,将 @objc dynamic
添加到 属性 将消除崩溃,但您将 看不到 两次 @IBOutlet
次浏览。
如果您将其作为 viewDidLoad()
的一部分调用(而不是 DispatchQueue.main.asyncAfter
):
override func viewDidLoad() {
super.viewDidLoad()
TestView.appearance().testColor = .red
}
两个 @IBOutlet
视图 将 获得红色背景。
或者,如果您向层次结构添加新视图,它将获得红色背景:
class AppearanceTestViewController: UIViewController {
@IBOutlet weak var testView: TestView!
@IBOutlet weak var testView2: TestView!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
TestView.appearance().testColor = .red
self.addAnotherTestView()
}
}
func addAnotherTestView() -> Void {
let v = TestView()
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
NSLayoutConstraint.activate([
v.widthAnchor.constraint(equalToConstant: 240.0),
v.heightAnchor.constraint(equalTo: v.widthAnchor),
v.centerXAnchor.constraint(equalTo: view.centerXAnchor),
v.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
// this newly added view WILL have a red background
}
}