我如何在响应通知时使SwiftUI View无效?



我是SwiftUI的新手,并试图开始在一个复杂的,现有的UIKit应用程序中使用它。该应用程序有一个主题系统,我不确定如何让SwiftUI视图响应主题更改事件。

主题对象看起来像

class ThemeService {
static var textColor: UIColor { get }
}
struct ViewTheme: {
private(set) var textColor = { ThemeService.textColor }
}

,当用户更改应用程序的主题时,返回的值ThemeService.textColor会发生变化。在应用程序的UIKit部分,视图观察"themeChanged"Notification,并从它们的主题结构中重新读取textColor属性的值。

我不确定如何管理这个SwiftUI。由于ViewTheme不是对象,我不能使用@ObservableObject,但它的textColor属性也不会随着主题的变化而改变;只是调用它返回的值发生了变化。

是否有办法让SwiftUI从外部事件重新呈现视图层次结构,而不是从视图看到的值的变化?还是说我应该换个方法?

你的答案工作得很好,但它需要采用ObservableObject。这里有一个替代的答案,使用你现有的NotificationCenter通知来更新SwiftUI视图。

struct MyView: View {
@State private var textColor: UIColor
var body: some View {
Text("Hello")
.foregroundColor(Color(textColor))
.onReceive(NotificationCenter.default.publisher(for: Notification.Name("themeChanged"))) { _ in
textColor = ThemeService.textColor
}
}
}

这需要一个@State变量来保存主题的当前数据,但这是正确的,因为SwiftUI视图实际上只是视图当前应该显示的内容的快照。理想情况下,它不应该引用任意更改的数据,因为这会导致数据同步问题,如您所问的问题。所以在SwiftUI视图中,直接在正文中编写ThemeService.textColor是有问题的,除非你确定在之后总是会发生更新,如果主题发生了变化。

我能够通过稍微欺骗主题系统并将ViewTheme更改为对象来实现此工作:

class ViewTheme: ObservableObject {
private(set) var textColor = { ThemeService.textColor }
init() {
NotificationCenter.default.addObserver(forName: Notification.Name("themeChanged"), 
object: nil, queue: .main) { [weak self] _ in
self?.objectWillChange.send()     
}
}
}

现在视图可以用@ObservedObject标记它,并将在"themeChanged"通知被触发时重新生成。

这似乎工作得很好,但我不确定是否有非明显的问题,我错过了这个解决方案。

最新更新