swiftswiftuiswiftui-listswiftui-navigationviewswiftui-view

Conflicting arguments to generic parameter Content, RowContent when using a custom view is used inside List and NavigationView


I'm trying to create a simple ToDo App for practice. I created a DataModel for struct Task and tried to use it to iterate in a List in a NavigationView. When I write code like this, it works fine.

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(DataModel.data, id: \.id) { object in
                HStack {
                    object.finished == true ?
                    Label(object.description, systemImage: "checkmark.circle") :
                    Label(object.description, systemImage: "circle")
                }
            }
        }
    }
}

I see the UI being rendered like this.

Expected UI

However, when I move the HStack into a custom view called TaskView, I'm getting multiple errors on lines NavigationView and List. The errors are as follows.

Conflicting arguments to generic parameter 'Content' ('<<hole>>' vs. '<<hole>>' vs. '<<hole>>' vs. '<<hole>>')

Conflicting arguments to generic parameter 'Content' ('NavigationView<<<hole>>>' vs. 'NavigationView<<<hole>>>')

Conflicting arguments to generic parameter 'Content' ('ForEach<[Task], Int, <<hole>>>' vs. 'ForEach<[Task], Int, <<hole>>>' vs. 'ForEach<[Task], Int, <<hole>>>' vs. 'ForEach<[Task], Int, <<hole>>>')

Conflicting arguments to generic parameter 'Content' ('List<Never, ForEach<[Task], Int, <<hole>>>>' vs. 'List<Never, ForEach<[Task], Int, <<hole>>>>')

Conflicting arguments to generic parameter 'RowContent' ('<<hole>>' vs. '<<hole>>')

Here is the source code for both the ContentView and TaskView in failing case.

ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(DataModel.data, id: \.id) { object in
                TaskView(finished: object.finished, description: object.description)
            }
        }
    }
}

TaskView.swift

import SwiftUI

struct TaskView: View {
    
    @Binding var finished: Bool
    @Binding var description: String
    
    var body: some View {
        HStack {
            finished == true ?
                Label(description, systemImage: "checkmark.circle") :
                Label(description, systemImage: "circle")
        }
    }
}

struct TaskView_Previews: PreviewProvider {
    
    @State static var finished = false
    @State static var description = "Persimmons"
    
    static var previews: some View {
        TaskView(finished: $finished, description: $description)
    }
}

DataModel.swift

import UIKit

struct MyTask: Hashable {
    var id: Int
    var finished: Bool
    var description: String
}

class DataModel: NSObject {
    static let data: [MyTask] = [
        MyTask(id: 0, finished: false, description: "Onions"),
        MyTask(id: 1, finished: true, description: "Tomatoes"),
        MyTask(id: 2, finished: false, description: "Persimmons"),
        MyTask(id: 3, finished: false, description: "Pasta")
    ]
}

Can any one tell me why I'm getting this error and how to resolve this error and what is the right way to create a CustomView?

Update

Following change to TaskView seems to have done the trick. Removing @Binding resolved the errors and the UI is rendered. However, not sure how the changes to datamodel are propagated in that case, but that is for another time.

struct TaskView: View {
    
    var finished: Bool
    var description: String
    
    var body: some View {
        HStack {
            finished == true ?
            Label(description, systemImage: "checkmark.circle").foregroundColor(Color.gray) :
                Label(description, systemImage: "circle").foregroundColor(Color.black)
        }.padding(.leading).padding(.bottom)
        .frame(maxWidth: .infinity, alignment: .leading)
    }
}

Solution

  • Based on the the comments, following change to TaskView seems to have done the trick. Removing @Binding resolved the errors and the UI is rendered.

    struct TaskView: View {
        
        var finished: Bool
        var description: String
        
        var body: some View {
            HStack {
                finished == true ?
                Label(description, systemImage: "checkmark.circle").foregroundColor(Color.gray) :
                    Label(description, systemImage: "circle").foregroundColor(Color.black)
            }.padding(.leading).padding(.bottom)
            .frame(maxWidth: .infinity, alignment: .leading)
        }
    }