Reputation: 1353
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
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
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
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