当 DateFormatter 格式更新时重新加载 SwiftUI 视图?

问题描述 投票:0回答:1

强制更新相关,我希望 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)
  }
}

有没有一种解决方案可以在不引入第三个变量的情况下重新加载视图?

swift swiftui nsdateformatter
1个回答
0
投票

可以按如下方式完成:

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)
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.