Type of expression is ambiguous without more context in Xcode 11

Viewed 29145

I'm trying to refer to an [Item] list within an @EnvironmentObject however when accessing it within a SwiftUI List, I get the error. What I don't understand is, this error doesn't pop up when following Apple's Landmark tutorial.

As far as I can tell, the [Item] list is loading correctly as I can print it out and do other functions with it. It just bugs out when using it for a SwiftUI List Is there something I've missed?

ItemHome.swift:

struct ItemHome : View {

    @EnvironmentObject var dataBank: DataBank

    var body: some View {
        List {
            ForEach(dataBank.itemList) { item in
                Text("\(item.name)") // Type of expression is ambiguous without more context
            }
        }
    }
}

Supporting code below:

Item Struct:

struct Item {

    var id: Int
    var uid: String
    var company: String
    var item_class: String
    var name: String
    var stock: Int
    var average_cost: Decimal
    var otc_price: Decimal
    var dealer_price: Decimal
    var ctc_price: Decimal
}

DataBank.swift:

final class DataBank : BindableObject {
    let didChange = PassthroughSubject<DataBank, Never>()

    var itemList: [Item] = load("itemsResults.json") {
        didSet {
            didChange.send(self)
        }
    }
}

func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
let data: Data

guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
    else {
        fatalError("Couldn't find \(filename) in main bundle.")
}

do {
    data = try Data(contentsOf: file)
} catch {
    fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}

do {
    let decoder = JSONDecoder()
    return try decoder.decode(T.self, from: data)
} catch {
    fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}

}

itemsResults.json:

[
    {
        "id": 1,
        "uid": "a019bf6c-44a2-11e9-9121-4ccc6afe39a1",
        "company": "Bioseed",
        "item_class": "Seeds",
        "name": "9909",
        "stock": 0,
        "average_cost": 0.0,
        "otc_price": 0.0,
        "dealer_price": 0.0,
        "ctc_price": 0.0
    },
    {
        "id": 2,
        "uid": "a019bf71-44a2-11e9-9121-4ccc6afe39a1",
        "company": "Pioneer",
        "item_class": "Seeds",
        "name": "4124YR",
        "stock": 0,
        "average_cost": 0.0,
        "otc_price": 0.0,
        "dealer_price": 0.0,
        "ctc_price": 0.0
    }
]
5 Answers

Apparently I missed making sure my models (Item in this case) conformed to the Identifiable protocol fixed it. Still, I wish Apple was more clear with their error messages.

As you mentioned in your answer, a ForEach needs a list of Identifiable objects. If you don't want to make your object implement that protocol (or can't for some reason), however, here's a trick:

item.identifiedBy(\.self)

I had the same problem and it wasn't something related to the line itself, it was related to the curly braces/brackets, so that if someone faced the same problem and doesn't know where the problem is, try to trace the curly braces and the brackets

To conform to Identifiable, just give the id or uid variable a unique value.

An easy way to do this is this:

var uid = UUID()

So your full struct would be:

struct Item: Identifiable {

    var id: Int
    var uid = UUID()
    var company: String
    var item_class: String
    var name: String
    var stock: Int
    var average_cost: Decimal
    var otc_price: Decimal
    var dealer_price: Decimal
    var ctc_price: Decimal
}

Xcode may show this error in many cases. Usually when using higher order functions (like map) and reason may be "anything".

There are two types:

  1. Error is in higher order function. In this case your only option is to carefully read the block of code. Once again there may be different kinds of problems.

  2. In some cases higher order function does not have any problem by itself, but there may be a compile time error in function that's called from the body of the higher order function. Unfortunately Xcode does not point to this error sometimes.

    To detect such errors and save lot of time, easy workaround is to temporarily comment higher order function and try to build. Now Xcode will show this error function and will show more reasonable error.

Related