某些用户界面设置无法自动使用“暗/亮”模式更改为UIColor
。例如层中的shadow
。因为我需要在暗和亮模式下删除阴影,所以需要在某个地方放置updateShadowIfNeeded()
函数。我知道如何检测当前的模式:
func dropShadowIfNeeded() {
switch traitCollection.userInterfaceStyle {
case .dark: removeShadow()
case .light: dropShadowIfNotDroppedYet()
default: assertionFailure("Unknown userInterfaceStyle")
}
}
现在,我将函数放在layoutSubviews
中,因为每次外观更改时都会调用该函数:
override func layoutSubviews() {
super.layoutSubviews()
dropShadowIfNeeded()
}
但是此功能被称为很多。仅在userInterfaceStyle
更改后才能触发的正确功能是什么?
答案 0 :(得分:3)
我在WWDC 2019 - Session 214找到了答案,大约是23:30。
正如我预期的那样,包括更改颜色时,都会调用此函数。除了ViewController
和presentationController
的许多其他功能之外。但是有一个专门设计的功能,在所有View
代表中都有类似的签名。
看看该会话中的这张图片:
灰色:打电话,但不适合我的问题,绿色:专为此设计
所以我应该调用它并在此函数中检查它:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
dropShadowIfNeeded()
}
}
这将确保每次更改仅被调用一次。
答案 1 :(得分:1)
我认为应该不那么频繁地调用它,此外,防护措施还可以确保您仅对用户界面样式更改做出反应:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard previousTraitCollection?.userInterfaceStyle != traitCollection.userInterfaceStyle else {
return
}
dropShadowIfNeeded()
}
答案 2 :(得分:0)
使用RxSwift和ObjectiveC运行时,无需继承即可实现
这是封装的版本:
import UIKit
import RxSwift
import RxCocoa
enum SystemTheme {
static func get(on view: UIView) -> UIUserInterfaceStyle {
view.traitCollection.userInterfaceStyle
}
static func observe(on view: UIView) -> Observable<UIUserInterfaceStyle> {
view.rx.methodInvoked(#selector(UIView.traitCollectionDidChange(_:)))
.map { _ in SystemTheme.get(on: view) }
.distinctUntilChanged()
}
}