0

I want to create different views by using only one class instance. My goal is not to create a separate instance for each view(group), instead, I would like to pass data through all views. Every time I try to pass data from another view I am faced with "Cannot use instance member within property initializer" and "Generic parameter 'C' could not be inferred" errors. For clarifying my problem I added some example code and marked errors as a comment.

class DataService {
    
    static let group1: [Person] = [
        Person(name: "Jack", age: 21),
        Person(name: "Anna", age: 29),
        Person(name: "Steve", age: 12),
        Person(name: "Carl", age: 16),
    ]
    
    static let group2: [Person] = [
        Person(name: "Crag", age: 19),
        Person(name: "Daniel", age: 29),
        Person(name: "Katty", age: 36),
        Person(name: "Leo", age: 13),
    ]
    
}

struct Person {
    let name: String
    let age: Int
}

class PersonClass: ObservableObject {
    
    @Published var peopleArray: [Person]
    
    init(data: [Person]) {
        self.peopleArray = data
    }
}

struct humanView: View {
    
    let data: [Person]
    
    @StateObject var person = PersonClass(data: data) // Error1: Cannot use instance member 'data' within property initializer
    
    var body: some View {
        
        VStack {
            ForEach(person.peopleArray.indices, id: \.self) { index in // Error2: Generic parameter 'C' could not be inferred
                Rectangle()
                    .fill(Color.black)
                    .frame(width: 120, height: 120)
                    .cornerRadius(10)
                    .overlay(
                        Text(person.peopleArray[index].name)
                            .font(.headline)
                            .foregroundColor(.white)
                    )
            }
        }
    }
}
     
struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink("Group 1") {
                humanView(group: DataService.group1)
            }
            NavigationLink("Group 2") {
                humanView(group: DataService.group2)
            }
        }
    }
}
2
  • What's the reason in having PersonClass here? Use injected data directly in ForEach. Also this should be helpful stackoverflow.com/a/62636048/12299030. Commented Aug 3, 2022 at 19:52
  • Imagine I have a game view with different levels and I'd like to draw game components by level. I've check the article I think .onAppear() might be useful. Thank you. Commented Aug 3, 2022 at 21:15

1 Answer 1

1

You should use "@State" variable PersonClass. There is the anwser

class PersonClass {
    var peopleArray: [Person]
    
    init(data: [Person]) {
        self.peopleArray = data
    }
}

struct humanView: View {
    
    @State var personClass: PersonClass
    
    var body: some View {
        
        VStack {
            ForEach(personClass.peopleArray.indices, id: \.self) { index in // Error2: Generic parameter 'C' could not be inferred
                Rectangle()
                    .fill(Color.black)
                    .frame(width: 120, height: 120)
                    .cornerRadius(10)
                    .overlay(
                        Text(personClass.peopleArray[index].name)
                            .font(.headline)
                            .foregroundColor(.white)
                    )
            }
        }
    }
}
     
struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack{
                NavigationLink("Group 1") {
                    humanView(personClass: PersonClass(data: DataService.group1))
                }
                NavigationLink("Group 2") {
                    humanView(personClass: PersonClass(data: DataService.group2))
                }
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

When I use @State var personClass: PersonClass it creates view once but, when I change class properties view doesn't update accordingly. Instead, I've done the same approach with @StateObject and it works as expected. I could update view from another class and also I don't need to initialize different object each time. Thank you.

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.