【问题标题】:How trigger state change / redraw on toggle change in SwiftUI如何在 SwiftUI 中触发状态更改/重绘切换更改
【发布时间】:2021-07-05 03:57:45
【问题描述】:

我有一些项目并在视图上显示项目计数。我有一个切换,可以减少计数/项目列表中显示的内容。当我使用切换时,项目计数不会更新。我在这里想念什么?为简洁起见减少/模拟示例。

struct SampleView: View {

    @State var items:[Item]
    @State var easyMode:Bool = false
    @State var filtered:[Item] = []

    init(...) {
        // Fill items and filtered array
    }

    var body: some View {

            Toggle(isOn: $easyMode, label:{
                Text("Easy mode")
            })
            .onChange(of: self.easyMode, perform: { value in
                filtered = filterItems()
                //         ^^ This is running but not
                //            updating stuff
            })
            // This text field does not update when filter changes
            Text(String(filtered.count) + " items")
    }
}

我尝试让 filterItems 在 @State var countLabel:String 中生成文本字符串并更新文本,但存在后台线程问题。所以我认为 filterItems 没有做任何事情有一些奇怪之处,因为它在一个单独的线程上。我错过了什么?谢谢!!

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    你可以试试这个:

    .onChange(of: self.easyMode) { value in
        DispatchQueue.main.async {
           filtered = filterItems()
        }
    }
    

    【讨论】:

      【解决方案2】:

      我刚刚获取了您的代码并使其可编译。

      struct SOTest: View {
          @State var items:[String]
          @State var easyMode:Bool = false
          @State var filtered: [String]
          
          init() {
              let tmp = ["1","2_","3","4_","5_","6"]
              self.items = tmp
              self.filtered = tmp.filterStrings()
          }
      
          var body: some View {
      
                  Toggle(isOn: $easyMode, label:{
                      Text("Easy mode")
                  })
                  .onChange(of: self.easyMode, perform: { value in
                      
                      if value {
                          filtered = items.filterStrings()
                      } else {
                          filtered = items
                      }
                  })
                  Text(String(filtered.count) + " items")
          }
      }
      
      extension Array where Element == String {
          func filterStrings() -> [String] {
              self.filter{ $0.contains("_") }
          }
      }
      

      一切正常。

      可能您在原始代码中做错了什么,在您的问题中您丢失了一些重要的东西。

      尝试在这里查看我的答案,也许您会找到隐藏问题的解决方案:SwiftUI: Forcing an Update

      并且....顺便说一句,这里有更简单的方法:

      struct SOTest: View {
          @State var items:[String]
          @State var easyMode:Bool = false
          @State var filtered: [String]
      
          init() {
              let tmp = ["1","2_","3","4_","5_","6"]
              self.items = tmp
              self.filtered = tmp.filterStrings()
          }
      
          var body: some View {
              Toggle(isOn: $easyMode, label:{
                  Text("Easy mode")
              })
              
              if easyMode {
                  Text(String(filtered.count) + " items")
              }
              else {
                  Text(String(items.count) + " items")
              }
          }
      }
      

      【讨论】:

      • 哇!太棒了。嗯,这令人困惑,我花了一个小时试图找出它为什么不起作用....我正在慢慢地将代码从真实项目复制并粘贴到测试项目中,以找出问题所在
      猜你喜欢
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 1970-01-01
      • 2018-12-08
      相关资源
      最近更新 更多