如何将数组从一个视图传递到另一个视图并相应地更新视图
How to pass an array from a view to another and update the view accordingly
我的 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)
}
}
}
}
知道如何解决这个问题吗?
提前致谢
问题是你传递的是一个数组,它是一个值类型(数组、字符串、字典、结构等都是值类型)。当您传递该数组时,您(有效地)将其中数据的新副本传递给新视图。您在那里所做的更改不会影响您的第一个视图中的数组,然后必须传回旧视图,这对于保持同步有点混乱。
相反,您想使用引用类型(class),其中传递给新视图的变量实际上只是指向相同数据(class 实例)的指针第一个视图的变量指向。然后,当任何视图或函数作用于该变量时,它将编辑相同的实例数据。
通过多视图应用程序来回传递数据非常方便。
唯一的问题是您不能在 classes 上使用 @State
包装器。但是 classes 有一个相当简单的等价物。
您需要首先创建符合协议 ObservableObject
的 class,然后将其任何属性声明为 @Published
。然后在您的视图中将 classes 实例化为 @ObservedObjects
因此,将您的新项目分解为 class
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
中,您必须实例化 class 并以不同的方式调用其 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 class 的一个实例传递给您的 MyListView
,这意味着两个视图将在 NewItems
中共享相同的数据。一种观点的改变会影响另一种观点。来来回回,随心所欲,做出改变,它会奏效的。
以下是您如何处理 MyListView
中的新 class 实例:
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)
}
}
}
}
要在多个视图(或多个函数等)之间共享相同的数据,您可以简单地将其包装在 class 中。然后将对该 class 实例中的相同数据进行任何视图的更改。
您甚至可以更进一步,用 @EnvironmentObject
包装 NewItems
实例,这样您甚至不必在 NavigationLink
的视图之间传递它.此处有更多详细信息:https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views
变化:
struct MyListView: View {
@Binding var newItems: Array = []
收件人:
struct MyListView: View {
@Binding var newItems: Array
问题是在您的 MyListView 中,您将绑定数组替换为不同的本地空数组。
当您传入 @Binding
值时,您绝不会在目标视图中对其进行初始化!
我的 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)
}
}
}
}
知道如何解决这个问题吗?
提前致谢
问题是你传递的是一个数组,它是一个值类型(数组、字符串、字典、结构等都是值类型)。当您传递该数组时,您(有效地)将其中数据的新副本传递给新视图。您在那里所做的更改不会影响您的第一个视图中的数组,然后必须传回旧视图,这对于保持同步有点混乱。
相反,您想使用引用类型(class),其中传递给新视图的变量实际上只是指向相同数据(class 实例)的指针第一个视图的变量指向。然后,当任何视图或函数作用于该变量时,它将编辑相同的实例数据。
通过多视图应用程序来回传递数据非常方便。
唯一的问题是您不能在 classes 上使用 @State
包装器。但是 classes 有一个相当简单的等价物。
您需要首先创建符合协议 ObservableObject
的 class,然后将其任何属性声明为 @Published
。然后在您的视图中将 classes 实例化为 @ObservedObjects
因此,将您的新项目分解为 class
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
中,您必须实例化 class 并以不同的方式调用其 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 class 的一个实例传递给您的 MyListView
,这意味着两个视图将在 NewItems
中共享相同的数据。一种观点的改变会影响另一种观点。来来回回,随心所欲,做出改变,它会奏效的。
以下是您如何处理 MyListView
中的新 class 实例:
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)
}
}
}
}
要在多个视图(或多个函数等)之间共享相同的数据,您可以简单地将其包装在 class 中。然后将对该 class 实例中的相同数据进行任何视图的更改。
您甚至可以更进一步,用 @EnvironmentObject
包装 NewItems
实例,这样您甚至不必在 NavigationLink
的视图之间传递它.此处有更多详细信息:https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views
变化:
struct MyListView: View {
@Binding var newItems: Array = []
收件人:
struct MyListView: View {
@Binding var newItems: Array
问题是在您的 MyListView 中,您将绑定数组替换为不同的本地空数组。
当您传入 @Binding
值时,您绝不会在目标视图中对其进行初始化!