Home > Blockchain >  How to pass an Object to new SwiftUI view
How to pass an Object to new SwiftUI view

Time:09-22

I'm having trouble getting started in SwiftUI. What I want to do is rather simple at least I thought it would. What I want to do is that the ContentView expects a first and last name of a person. The button "Add to list" adds the person to a list and the second button shows a list of all added persons in a second view. I read about the property wrappers but I cannot get it to work. Do I need to change struct Person to a class in order to use the @ObservedObject for initialising @StateObject var listOfPersons = [Person]() or is there a more simpler Swift like way to pass the list to my PersonList View? My project code:

ContentView.swift

struct ContentView: View {
    @State var firstName: String = ""
    @State var lastName: String = ""
    @StateObject var listOfPersons = [Person]()
    
    var body: some View {
        NavigationView {
            ZStack (alignment: .top){
                Color(.orange).opacity(0.2).edgesIgnoringSafeArea(.all)
                VStack {
                    Text("Hello stranger")
                        .font(.title)
                    TextField("Fist name:", text: $firstName)
                        .padding()
                    TextField("Last name:", text: $firstName)
                        .padding()
                    HStack(spacing: 40) {
                        Button("Add to list") {
                            listOfPersons.append(Person(firstName: firstName, lastName: lastName))
                        }
                        .padding()
                    
                        NavigationLink(destination: PersonList()) {
                           Text("Show list")
                        }
    ...
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

PersonList.swift

import SwiftUI

struct PersonList: View {
    @Binding var listOfPersons = [Person]()
    
    var body: some View {
        Color(.orange).opacity(0.2).edgesIgnoringSafeArea(.all)
        List(listOfPersons) { person in
            PersonRow(person: person) }
    }
}


struct PersonList_Previews: PreviewProvider {
    static var previews: some View {
        PersonList()
    }
}

Person.swift

import Foundation

struct Person {
    var firstName: String
    var lastName: String
}

PersonRow.swift

import SwiftUI

struct PersonRow: View {
    var person: Person
    
    var body: some View {
        Text("\(person.firstName), \(person.lastName)")
    }
}

CodePudding user response:

Your code has a couple problems, but you're on the right track. First, replace @StateObject var listOfPersons = [Person]() with:

@State var listOfPersons = [Person]()

@StateObject is for an instance of a ObservableObject class. @State is what you should be using for a simple array of the Person struct.

Then, in your current code, you're just instantiating a plain PersonList without any parameters. You want to pass in listOfPersons.

                                       /// here!
NavigationLink(destination: PersonList(listOfPersons: $listOfPersons)) {
    Text("Show list")
}

The $ sign gets the underlying Binding<[Person]> from listOfPersons, which means that any changes made inside PersonList's listOfPersons will be reflected back to ContentView's listOfPersons.

Finally, in PersonList, change @Binding var listOfPersons = [Person]() to

struct PersonList: View {
    @Binding var listOfPersons: [Person]
    ...
}

@Binding almost never needs to have a default value, since it's always passed in.

  • Related