SwiftUI - 将数据传递到不同的 View

标签 swift xcode swiftui

我正在开发一个有 4 个不同 View 的应用程序。主 View ( ContentView )、一个 AddView 、一个 EditView 和一个单独的 DataView ,其中我通过一个 将所有数据传递给其他 ObservableObject。

在主 View 中,我有一个项目列表。在 AddView 中,我将项目添加到该列表和 ContentView 中。我希望能够使用导航链接编辑添加的项目。因此,从主 View 中,我想转到 EditView ,更改值并再次返回 ContentView 在那里我看到更改的值。

你会使用 ObservableObject 来做这件事还是我需要 EnvironmentObject?因为目前 EditView 不工作,我无法将数据从 ContentView 传递到 EditView EditView 上的所有文本字段都是空的,值不会被传递。它可以将数据从 AddView 传递到 ContentView 但不能从 ContentView 传递到 EditView

有人能告诉我如何将数据链接到所有 View 吗?

最佳答案

您应该使用 @EnvironmentObject 。它允许共享一个对象,这对于将数据共享给其他 View 非常重要。
我在这个例子中使用了一个 Shopping 对象。这个应用程序就像一个购物 list 。整个项目可从 GitHub here 获得。
我真的希望这很有用,因为它花了很长时间。这只是如何在 @EnvironmentObject 之间有效使用 View 的一般示例。
该应用程序如下所示:
How the app looks

创建项目
(可以通过 GitHub 下载,见上面的链接)
1: 首先,在您的 SceneDelegate.swift 中,替换:

let contentView = ContentView()
和:
let contentView = ContentView().environmentObject(Shopping())
2: Xcode 现在会提示 Shopping 还没有被制作出来,所以我们接下来会解决这个问题:
class Shopping: ObservableObject {
    
    @Published var list = [
        ShoppingItem("Bread", quantity: 1),
        ShoppingItem("Milk", quantity: 2),
        ShoppingItem("Eggs", quantity: 12)
    ]
    
    func addItem(_ item: ShoppingItem) {
        list.append(item)
    }
}


class ShoppingItem: Identifiable {
    
    var name: String
    var quantity: Int
    
    init(_ name: String, quantity: Int) {
        self.name = name
        self.quantity = quantity
    }
}
3: 接下来,我们要主要内容, ContentView :
struct ContentView: View {

    @EnvironmentObject private var shopping: Shopping
    @State private var newItem: String?
    
    var body: some View {
        NavigationView {
            List {
                ForEach(shopping.list) { item in
                    NavigationLink.init(destination: EditView(currentItem: item)) {
                        HStack {
                            Text(item.name)
                            Spacer()
                            Text(String(item.quantity))
                            Spacer().frame(width: 10)
                        }
                    }
                }
                
                if newItem != nil {
                    TextField("New Item", text: $newItem.bound, onCommit: {
                        if !self.newItem!.isEmpty {
                            self.shopping.addItem(ShoppingItem(self.newItem!, quantity: 1))
                        }
                        self.newItem = nil
                    })
                }
            }
            .navigationBarTitle("Shopping List")
            .navigationBarItems(trailing: Button(action: {
                self.newItem = ""
            }, label: {
                Image(systemName: "plus.circle.fill")
                    .resizable()
                    .frame(width: 25, height: 25)
            }))
        }
    }
}
4: 与这个 extension 一起让可选的 @State 工作(信用 here ,虽然这已经简化了):
extension Optional where Wrapped == String {

    var bound: String {
        get {
            return self ?? ""
        }
        set {
            self = newValue
        }
    }
}
5: 最后 - EditView ,允许您编辑购物 list 中的项目名称:
struct EditView: View {

    let currentItem: ShoppingItem
    @EnvironmentObject private var shopping: Shopping
    @State private var name = ""
    
    var body: some View {
        TextField("Item", text: $name, onCommit: saveName)
            .padding()
            .background(Color.gray)
            .onAppear(perform: setName)
    }
    
    private func saveName() {
        shopping.objectWillChange.send()
        currentItem.name = name
    }
    private func setName() {
        name = currentItem.name
    }
}

关于SwiftUI - 将数据传递到不同的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59770333/

相关文章:

swift - 仅在边缘上描边 CGPath

ios - Swift - 使用 animateWithDuration 淡化 CAGradientLayer

xcode - 升级到 El Capitan 后出现无效的事件开发者路径错误

ios - 当在 View 中注入(inject)实体时,SwiftUI 预览版无法使用核心数据

swift - 在 SwiftUI 中更新树结构的 UI

qr-code - 使用 SwiftUI 生成二维码显示空图片

ios - 在处理关系 Segue 时,iOS 8 的 "Storyboard Reference"的替代方案?

ios - 如何使用服务帐户 key .p12访问Google表格API

ios - 是否可以在 iOS 11 中自定义集群图像?

ios - .ondelete 带有部分的 SwiftUI 列表