Subcreation
Subcreation

Reputation: 1353

Getting error "Generic parameter 'Label' could not be inferred" with SwiftUI tutorial code

I'm working through this SwiftUI tutorial here: https://developer.apple.com/tutorials/swiftui/handling-user-input

And on Step 3 of the section "Adopt the Model Object in Your View", I get this error on the Toggle statement in line 16: "Generic parameter 'Label' could not be inferred."

My code is identical to that provided in the tutorial:

import SwiftUI

struct LandmarkList: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        NavigationView {
            List {
                Toggle(isOn: $userData.showFavoritesOnly) {
                    Text("Favorites Only")
                }
                ForEach(userData.landmarkData) { landmark in
                    if !self.userData.showFavoritesOnly || landmark.isFavorite {
                        NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                            LandmarkRow(landmark: landmark)
                        }
                    }
                }
            }
            .navigationBarTitle(Text("Landmarks"))
        }
    }
}

struct LandmarkList_Previews: PreviewProvider {
    static var previews: some View {
        ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
            LandmarkList()
                .previewDevice(PreviewDevice(rawValue: deviceName))
                .previewDisplayName(deviceName)
        }
    }
}

When I look at the code provided in the "Complete" folder, I see its nearly identical, except that the userData variable is made private—which I added to my "StartingPoint" version, though I can't imagine why it'd make a difference, and of course it still gives the same error and won't build. I can build and run the Complete version, so clearly the message about requiring a Generic parameter is wrong and it must have to do with something else like how the project is configured in settings.

I remember getting stuck earlier this summer with a similar issue in a different part of the tutorial, and found a post where someone explained why code would work in one project and not another, but I can't find that post now.

Is anyone familiar with this issue? Is there something else I need to understand about how to configure my project before I can reference an observable object in a toggle control in my view like this?

Upvotes: 7

Views: 3637

Answers (3)

SolidCoder
SolidCoder

Reputation: 184

I had the exact same problem today and Ravi Mishra's comment resolved the issue for me (kudos to you). It must've been an autocomplete mistake.

ForEach(userData.landmarkData) should instead be ForEach(userData.landmarks)

Upvotes: 1

NSBob
NSBob

Reputation: 191

I bothered my head about this tutorial for a week, went line by line through it twice by downloading the tutorial files again. I made sure that every character of my work in the tutorial matched every character of the completed project--twice--and still that nasty error message popped up as soon as I entered the final code. Stack Overflow was my last stop; when I read the solution was to include '.environmentObject(UserData())', I went right to my code to add it but it was already there!
Out of pure desperation, I decided to copy the (exact same) code for the body from the source of the completed project to the source in my tutorial project. The error disappeared.
I think @krjw has a point.

Upvotes: 0

krjw
krjw

Reputation: 4450

So as I mentioned in the comments: Just add .environmentObject(UserData()) under the ForEach() in your LandmarkList_Previews struct.

That would result in:

import SwiftUI

struct LandmarkList: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        NavigationView {
            List {
                Toggle(isOn: $userData.showFavoritesOnly) {
                    Text("Favorites Only")
                }
                ForEach(userData.landmarkData) { landmark in
                    if !self.userData.showFavoritesOnly || landmark.isFavorite {
                        NavigationLink(destination: LandmarkDetail(landmark: landmark)
                            .environmentObject(self.userData)
                        ) {
                            LandmarkRow(landmark: landmark)
                        }
                    }
                }
            }
            .navigationBarTitle(Text("Landmarks"))
        }
    }
}

struct LandmarkList_Previews: PreviewProvider {
    static var previews: some View {
        ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
            LandmarkList()
                .previewDevice(PreviewDevice(rawValue: deviceName))
                .previewDisplayName(deviceName)
        }.environmentObject(UserData())
    }
}

Upvotes: 3

Related Questions