【问题标题】:How to execute a function in a SwiftUI sub-view?如何在 SwiftUI 子视图中执行函数?
【发布时间】:2020-12-08 19:27:23
【问题描述】:

这是一个关于 SwiftUI 的一般性理解问题。

我希望能够执行与另一个视图关联的功能。这样做有很多案例/原因。我最近的努力是创建一个可以收集多个字段(例如地址)的视图,然后在其他视图中使用该视图。

我的问题是,如何从地址视图中获取数据?在所示示例中,我如何调用getXML() 函数?有没有更好的方法来做到这一点?

import SwiftUI

struct AddressView: View
{
    @State var street1 = ""
    @State var street2 = ""
    @State var city = ""
    @State var state = ""
    @State var zip = ""

    var body: some View
    {
        VStack
        {
            TextField("Street1", text: $street1)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            TextField("Street2", text: $street2)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            TextField("City", text: $city)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            TextField("State", text: $state)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            TextField("Zip", text: $zip)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
        }.padding()
    }
    
    func getXML() -> String
    {
        var xml = XMLStuff("Address")
        xml.push(tag: "street1", value: street1)
        xml.push(tag: "street2", value: street2)
        xml.push(tag: "city", value: city)
        xml.push(tag: "state", value: state)
        xml.push(tag: "zip", value: zip)
        return xml.string()
    }
}

以下是一些用于包含多个此类视图的代码,但我不知道如何提取数据以保存/使用它。

import SwiftUI

struct ContactView: View
{
    @State var name: String = ""
    
    var body: some View
    {
        VStack
        {
            TextField("Name", text: $name)
            AddressView()
            PhoneView()
        }
    }
}

我知道我可以在调用者中创建一堆状态变量,然后将它们传递给子视图,但我会尽量避免这种情况。

【问题讨论】:

  • 你需要一个由 ContactView 拥有并传递给 AddressView 的视图模型,而不是一堆状态,它会修改它,父视图只需使用它,getXML 可以放置在该视图模型中类。

标签: swift view swiftui


【解决方案1】:

您可以创建一个ObservableObject 类来存储您的属性:

class ContactViewModel: ObservableObject {
    @Published var street1 = ""
    @Published var street2 = ""
    @Published var city = ""
    @Published var state = ""
    @Published var zip = ""

    func getXML() -> String {
        var xml = XMLStuff("Address")
        xml.push(tag: "street1", value: street1)
        xml.push(tag: "street2", value: street2)
        xml.push(tag: "city", value: city)
        xml.push(tag: "state", value: state)
        xml.push(tag: "zip", value: zip)
        return xml.string()
    }
}

然后,在ContentView中使用这个类:

struct ContactView: View {
    @StateObject private var viewModel = ContactViewModel()
    @State private var name: String = ""

    var body: some View {
        VStack {
            TextField("Name", text: $name)
            AddressView(viewModel: viewModel)
            ...
        }
    }
}

并将其传递给AddressView:

struct AddressView: View {
    @ObservedObject var viewModel: ContactViewModel

    var body: some View {
        VStack {
            TextField("Street1", text: $viewModel.street1)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            TextField("Street2", text: $viewModel.street2)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            TextField("City", text: $viewModel.city)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            TextField("State", text: $viewModel.state)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            TextField("Zip", text: $viewModel.zip)
                .textFieldStyle(RoundedBorderTextFieldStyle())

        }.padding()
    }
}

您也可以从ContentViewAddressView 调用getXML() 函数:

viewModel.getXML()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-09
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    相关资源
    最近更新 更多