如何在SwiftUI中更新列表?

时间:2019-06-26 04:26:36

标签: swiftui

我的代码比这复杂一点,所以我创建了一个示例,该示例得到了相同的错误。

当我导航到一个视图时,我要执行一个函数,并将一个变量传递到该视图中。然后,该函数生成一个数组。然后,我想将该数组放入列表中,但出现错误。

如何获取列表以显示生成的数组?

我认为问题在于列表无法更新,因为它已经具有声明的空白数组。

import SwiftUI

struct ContentView : View {

    @State var array = [String]()

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

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

}

5 个答案:

答案 0 :(得分:2)

您可以将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 :(得分:0)

  

愚蠢的UI是一个好的UI

让您的视图保持沉默,尝试以下代码创建动态列表


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 :(得分:0)

您可以使用Combine框架来更新列表。 每当在DataProvider Object中进行更改时,它将自动更新列表。

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()))

答案 3 :(得分:0)

@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" ]
}

答案 4 :(得分: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 {
      
  }
}