【问题标题】:Refreshing view by changing @State variable in SwiftUI not working通过更改 SwiftUI 中的 @State 变量来刷新视图不起作用
【发布时间】:2020-08-12 22:10:25
【问题描述】:

所以为了简单起见,我将首先描述我的代码的运行方式。我有一个使用 ForEach 循环遍历 AWS 数据库生成的列表。

List{
    ForEach(self.data.database1){ row in
         HStack {
              Button("\((row.name)!)") { 
                   self.selectedItem = row.id
                   self.selectedItemName = row.poi!
                   self.pressedItem = true
                                
              }
                            
              Spacer()
              Button("Delete") {
                  self.selectedItem = row.id
                  self.showDeleteItemView = true
          //this brings up a view that can confirm you want to delete
              }.buttonStyle(BorderlessButtonStyle())                        
                        }
                    }
                    
                }

列表中的每一行都包含一个“删除”按钮。此删除按钮打开如下视图:

if self.showDeleteEventView == true {
    ConfirmActionView(showView: self.$showDeleteItemView, actionName: "delete this event", function: {
              
                    for item in self.data.database1{
                        if self.selectedItem == item.id{
                            DispatchQueue.main.async {
                                self.data.deleteItem(id: event.id)
                                self.reloadView.toggle()
                            }
                        }
                    }
               
            }, buttonLabel: "Delete")
        }

观点是:

struct ConfirmActionView: View {
@Binding var showView: Bool
var actionName: String
var function: () -> Void
var buttonLabel: String
var body: some View {
    ZStack {
         VStack {
                HStack {
                    Spacer()
                    Button("X") {
                        self.showView = false
                    }
                }
                Text("Are you sure you want to \(self.actionName)?")
                    
                Spacer()
                HStack {
                    Button("\(self.buttonLabel)") {
                        print("confirmed action")
                        self.function()
                        self.showView = false
                    }
                   
                    
                    Button("Cancel") {
                        self.showView = false
                    }
                    .padding(EdgeInsets(top: 6, leading: 6, bottom: 6, trailing: 6))
                    
                }
                    
            }.frame(width: 300, height: 150)
            }
    }
}

deleteItem() 函数如下:

func deleteItem(id: Int) {
    let baseUrl = URL(string: itemUrl)
    let deletionUrl = baseUrl!.appendingPathComponent("\(id)")
    print("Deletion URL with appended id: \(deletionUrl.absoluteString)")

    var request = URLRequest(url: deletionUrl)
    request.httpMethod = "DELETE"
    print(token) // ensure this is correct
    request.allHTTPHeaderFields = ["Authorization": "Token \(token)"]
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        if let error = error {
            print("Encountered network error: \(error)")
            return
        }
        
        if let httpResponse = response as? HTTPURLResponse {
            // this is basically also debugging code
            print("Endpoint responded with status: \(httpResponse.statusCode)")
            print("                   with headers:\n\(httpResponse.allHeaderFields)")
        }
        // Debug output of the data:
        if let data = data {
            let payloadAsSimpleString = String(data: data, encoding: .utf8) ?? "(can't parse payload)"
            print("Response contains payload\n\(payloadAsSimpleString)")
        }
    }
    task.resume()
}

stateVariable1 是用于保存行中项目名称的变量。 reloadView 是一个@State 布尔变量,所以我想如果我切换它,视图应该在从数据库中删除项目后刷新。代码功能与我想象的一样,除了 reloadView 切换实际上并没有重新加载视图。

【问题讨论】:

  • 请出示您的代码(至少是 ForEach 部分)。
  • @pawello2222 嗨,pawello,我添加了包含 ForEach 的列表。如果您需要我添加 deleteItem() 函数,请告诉我
  • 你试过ForEach(self.data.database1, id: \.id) { row in吗?还是id: \.self
  • @pawello2222 你的意思是用 if 语句代替 for 循环?不,我没有,很抱歉,我不知道该放在哪里。

标签: swift database listview swiftui row


【解决方案1】:

如果您的数据可以更改,您需要ForEach 的动态变体。

尝试替换:

List {
    ForEach(self.data.database1) { row in
         HStack {
             ...

与:

List {
    ForEach(self.data.database1, id: \.id) { row in
         HStack {
             ...

编辑

在您删除项目后,您的数据似乎也没有刷新 - 您从服务器中删除它,而不是在本地删除。

您可以在删除项目后重新加载它:

func deleteItem(id: Int) {
    ...
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        ...
        if let data = data {
            let payloadAsSimpleString = String(data: data, encoding: .utf8) ?? "(can't parse payload)"
            print("Response contains payload\n\(payloadAsSimpleString)")
        }

        // here you can reload data from the server
        // or pass function (which reloads data) as a parameter and call it here
    }
    task.resume()
}

【讨论】:

  • 我尝试替换它-确认删除时视图的刷新没有变化。
  • 如果我添加 deleteItem() 函数会有帮助吗?
  • 我添加了您要求的所有内容。我知道这很多,但我试图解释和注释什么是重要的。非常感谢您,如果您能帮助我,我将永远感激不尽,哈哈
  • @nickcoding 所以在deleteItem 中,您向服务器发送请求以删除您的项目。但看起来您不再查询数据(self.reloadView.toggle() 不会做任何事情)。我建议您在删除项目后重新加载数据(因为它是异步的,您可能需要回调)。
  • @nickcoding 我用额外的步骤更新了我的答案。
猜你喜欢
  • 2020-04-10
  • 2021-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多