我有一个View1,该列表具有一个列表,一个View2的导航按钮以及一个基于数组中各项的数组,它将创建行。
在View2中,我有一个项目列表。
我希望用户转到View2并选择项目,然后将它们添加到存在于View1的数组中。然后,View1将使用新添加的项目进行更新。
问题在于将项目从一个视图传递到另一个视图。如果用户单击项目时View2返回View1,那也很好。
这是我尝试创建的不起作用的内容:
查看1
struct ContentView: View {
@State private var newItems : Array = []
var body: some View {
NavigationView {
List(){
Section(header:
HStack{
Image(systemName: "plus.square.fill")
Text("Find Items")
})
{
NavigationLink( destination: MyListView(newItems: self.$newItems) ){
Text("Add Items")
}
}
Section(header:
HStack{ Text("Items") }
) {
ForEach(newItems, id: \.self){ item in
Text("\(item)")
}
}
}
.navigationBarTitle("Items List")
.listStyle(GroupedListStyle())
}
}
}
查看2
struct MyListView: View {
@Binding var newItems: Array = []
var myArray = [1, 2, 3, 4]
var body: some View {
List(myArray, id: \.self ){i in
HStack{
Image(systemName: "photo")
Text("\(i)").font(.headline)
}.onTapGesture {
self.newItems.append(i)
print(self.newItems.count)
}
}
}
}
有什么办法解决这个问题吗?
预先感谢
答案 0 :(得分:2)
更改:
struct MyListView: View {
@Binding var newItems: Array = []
收件人:
struct MyListView: View {
@Binding var newItems: Array
问题在于,在MyListView中,您将绑定数组替换为其他本地空数组。
传递@Binding
值时,切勿在目标视图中初始化它!
答案 1 :(得分:0)
问题是您要传递一个数组,该数组是一种值类型(数组,字符串,字典,结构等是值类型)。当您传递该数组时,您(正在有效地)将其中的数据新副本传递给新视图。您在那里进行的更改不会影响您的第一个View中的数组,因此必须将其传递回旧的View中,以保持同步有点混乱。
相反,您想使用引用类型(一个类),其中传递给新View的变量实际上只是指向第一个View变量所指向的相同数据(类实例)的指针。然后,当ANY View或函数对该变量起作用时,它将编辑相同的实例数据。
超级方便,可通过多视图应用程序来回传递数据。 ?
唯一要注意的是,您不能在类上使用@State
包装器。但是类有一个相当简单的等效项。
您需要首先创建符合协议ObservableObject
的类,然后将其任何属性声明为@Published
。然后在您的视图中将类实例化为@ObservedObjects
所以将您的newItems分成一个类
class NewItems: ObservableObject {
@Published var items = [Int]()
// And any other properties you want to pass back and forth.
// Maybe even a complex Struct (which is a value type, but wrapped in a class)
}
然后在您的ContentView
中,必须实例化该类并以不同的方式调用其items
数组:
struct ContentView: View {
@ObservedObject var newItems: NewItems() // New instance of NewItems is created.
// FYI your array is now accessed by calling newItems.items like so:
// newItems.items = [1, 2, 3]
var body: some View {
NavigationView {
List(){
Section(header:
HStack{
Image(systemName: "plus.square.fill")
Text("Find Items")
})
{
// Now you're passing a pointer to the instance of the NewItems class
NavigationLink( destination: MyListView(newItems: self.$newItems) ){
Text("Add Items")
}
}
Section(header:
HStack{ Text("Items") }
) {
ForEach(newItems, id: \.self){ item in
Text("\(item)")
}
}
}
.navigationBarTitle("Items List")
.listStyle(GroupedListStyle())
}
}
}
因此,您要将NewItems类的实例传递给MyListView
,这意味着两个视图都将在该NewItems
中共享相同的数据。一个视图中的更改将影响另一个视图。来回移动所有所需的内容,进行更改,它就可以正常工作。
这是在MyListView
中处理新类实例的方式:
struct MyListView: View {
// We're getting a class now that has your [Int] within it
@ObservedObject var newItems: NewItems
var myArray = [1, 2, 3, 4]
var body: some View {
List(myArray, id: \.self ){i in
HStack{
Image(systemName: "photo")
Text("\(i)").font(.headline)
}.onTapGesture {
self.newItems.append(i)
// Make sure you call the items array within newItems
print(self.newItems.items.count)
}
}
}
}
要在多个视图(或多个函数等)之间共享相同的数据,只需将其包装在一个类中即可。然后,将对该类实例中的相同数据进行任何视图更改。
您甚至可以更进一步,并用NewItems
包装@EnvironmentObject
实例,因此您甚至不必在NavigationLink
的视图之间传递它。此处有更多详细信息:https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views