0

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)")
    }
}
2

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.