Reputation: 566
This is more of a general understanding question regarding SwiftUI.
What I would like to be able to do is to execute a function associated with another view. There are a number of cases/reasons for doing this. My most recent endeavor is to have a view that collects a number of fields, like an address, then to use that view within other views.
My question is, how do I get the data from the address view? In the example shown, how might I call the getXML()
function? Is there a better way to accomplish this?
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()
}
}
The following is some code that would be used to include several such views but I can't figure out how to extract the data in order to save/use it.
import SwiftUI
struct ContactView: View
{
@State var name: String = ""
var body: some View
{
VStack
{
TextField("Name", text: $name)
AddressView()
PhoneView()
}
}
}
I know I could create a bunch of state variables in the caller and then pass them to the sub-view, but I'm trying to avoid that if possible.
Upvotes: 2
Views: 2153
Reputation: 54426
You can create an ObservableObject
class to store your properties:
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()
}
}
Then, use this class in the 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)
...
}
}
}
and pass it to the 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()
}
}
You can also call the getXML()
function from either ContentView
or AddressView
:
viewModel.getXML()
Upvotes: 2