与强制更新相关,我希望 SwiftUI 在
DateFormatter
实例的 format
属性更改时重新加载并更新我的内容视图。
示例:
private extension String {
enum TimeDateFormat: String {
case civilian = "hh:mm a"
case military = "HH:mm"
init(is12h: Bool) {
self = is12h ? .civilian : .military
}
}
}
struct ContentView: View {
private let formatter = DateFormatter()
@State private var is24h: Bool = false
var body: some View {
Text(formatter.string(from: .now))
Button {
is24h.toggle()
formatter.dateFormat = .TimeDateFormat(is12h: !is24h).rawValue
// DOESN'T UPDATE THE VIEW
} label: {
Text("Toggle format")
}
}
init() {
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = .TimeDateFormat.civilian.rawValue
}
}
我尝试过使用
Text(Date.now, formatter: formatter)
,但不仅不更新格式,Text(_:formatter:)
甚至不应用我在 ContentView
初始化程序中设置的格式。
我还尝试过颠倒实例属性设置器的顺序。
// ...
formatter.dateFormat = .TimeDateFormat(is12h: is24h).rawValue
is24h.toggle()
// DOESN'T UPDATE THE VIEW
以下代码有效。然而,这段代码引入了第三个实例变量,这是我特别想避免的。
struct ContentView: View {
private let formatter = DateFormatter()
@State private var is24h: Bool = false
@State private var text: String
var body: some View {
Text(text)
Button {
is24h.toggle()
formatter.dateFormat = .TimeDateFormat(is12h: !is24h).rawValue
text = formatter.string(from: .now)
} label: {
Text("Toggle format")
}
}
init() {
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = .TimeDateFormat.civilian.rawValue
text = formatter.string(from: .now)
}
}
有没有一种解决方案可以在不引入第三个变量的情况下重新加载视图?
可以按如下方式完成:
struct ContentView: View {
private let formatter = DateFormatter()
@State private var is24h: Bool = false
@State private var formattedDate: String = ""
var body: some View {
Text(formattedDate)
.onChange(of: is24h) { newValue in
formatter.dateFormat = .TimeDateFormat(is12h: !newValue).rawValue
formattedDate = formatter.string(from: .now)
}
Button {
is24h.toggle()
} label: {
Text("Toggle format")
}
.onChange(of: is24h) { _ in }
.onAppear {
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = .TimeDateFormat.civilian.rawValue
formattedDate = formatter.string(from: .now)
}
}