如何在SwiftUI中更新列表?

16

我的代码比这个复杂一些,因此我创建了一个示例,可以得到相同的错误。

当我进入一个视图时,我想执行一个函数,并将一个变量传递到该视图中。该函数然后生成一个数组。然后,我想将该数组放入一个List中,但是我会遇到错误。

我该如何让List显示出生成的数组?

我认为问题在于List不能更新,因为它已经声明了一个空白数组。

struct ContentView : View {

    @State var array = [String]()

    var body: some View {
        List(self.array,id: \.self) { item in
            Text("\(item)")
            }
            .onAppear(perform: createArrayItems)
    }

    func createArrayItems() {
        array = ["item1", "item2", "item3", "item4", "item5"]
    }

}
5个回答

17
您可以使用ObservableObject数据提供程序(例如: ViewModel)和@Published属性。
struct ListView: View {
   @ObservedObject var viewModel = ListViewModel()

   var body: some View {
      NavigationView {
         List(){
            ForEach(viewModel.items) { item in
               Text(item)
            }
         }
      }  
   }
}



#if DEBUG

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
     ListView()
  }
}
#endif



class ListViewModel: ObservableObject {

   @Published var items = ["item1", "item2", "item3", "item4", "item5","item6"]

   func addItem(){
      items.append("item7")
   }
}

1
你可以使用Combine框架来更新列表。 当DataProvider对象发生更改时,它会自动更新列表。
struct ContentView : View {

    @EnvironmentObject var data: DataProvider

    var body: some View {
        NavigationView {
            NavigationButton(destination: SecondPage()) {
                Text("Go to Second Page")
            }
            List {
                ForEach(data.array.identified(by: \.self)) { item in
                    Text("\(item)")
                }
            }
        }
    }
}

在列表中添加项目。
struct SecondPage : View {
    @State var counter = 1
    @EnvironmentObject var tempArray: DataProvider
    var body: some View {
        VStack {
            Button(action: {
                self.tempArray.array.append("item\(self.counter)")
                self.counter += 1
            }) {
                Text("Add items")
            }
            Text("Number of items added \(counter-1)")
        }
    }
}

它将简单地通知更改。
import Combine

final class DataProvider: BindableObject {
    let didChange = PassthroughSubject<DataProvider, Never>()

    var array = [String]() {
        didSet {
            didChange.send(self)
        }
    }
}

你还需要在 SceneDelegate 中进行一些更新。这个更新确保 ContentView 在环境中拥有一个 DataProvider 对象。
 window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(DataProvider()))

1

@txagPman

我也有你的问题,不知道如何修改列表。 我写了这段代码。 希望对你有用。

    import SwiftUI

struct ContentView: View {

    @State private var array = createArrayItems()
    //     @State private var array = [""] - This work
    //    @State private var array = [] - This not work
    @State private var text = ""

    var body: some View {
        VStack {
            TextField("Text", text: $text, onCommit: {
//                self.array = createArrayItems() - This work after press return on textfield
                self.array.append(self.text)
            }).padding()
            List (self.array, id: \.self) {item in
                Text("\(item)")
            }
        }
//        .onAppear {
//            self.array = createArrayItems() - This not work
//        }
    }
}

func createArrayItems() -> [String] {
    return ["item_01","item_02","item_03","item_04" ]
}

0
使用这个:
class ObservableArray<T>: ObservableObject {
  @Published var array: [T]
  init(array: [T] = ) {
     self.array = array
  }
  init(repeating value: T, count: Int) {
     array = Array(repeating: value, count: count)
  }
}

struct YourView: View {
  @ObservedObject var array = ObservableArray<String>()
  var body: some View {
      
  }
}

0
一个简单的用户界面是一个好的用户界面。 尝试以下代码创建动态列表,保持你的视图简单。

import UIKit
import SwiftUI
import PlaygroundSupport

struct ContentView : View {
    @State var array = [String]()
    var body: some View {
                List{
                    ForEach(array.identified(by: \.self)) { item in
                    Text("\(item)")
                }
            }
        }
    }

func createArrayItems()->[String] {
    return ["item1", "item2", "item3", "item4", "item5","item6"]
}

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView(array: createArrayItems()))

2
identified(by: )在Xcode 11.1 GM Seed中已不再可用。请改为使用id: .self或id: .id。 - Carla Camargo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接