1

I'm getting a Expression type 'Binding<_>' is ambiguous without more context error at $order.quantity.contracts in the following code:

struct ContractsPickerView: View {
    @Binding var order: Order
    
    var question: String
            
    var body: some View {
                         
                        Error
                          |
                          |
                          V                
        Picker(selection: $order.quantity.contracts, label: Text("\(question)").font(.headline)) { 
            ForEach(0..<101, id: \.self) { contracts in
                Text("\(contracts)")
            }
        }
    }
}

In fact, Xcode is not offering me the contracts attribute in the Quantity class after typing $order.quantity.. Here are the models:

struct Order {
    var quantity: Quantity?
}

struct Quantity: Hashable {
    private var userEnteredContracts: Int?
    var contracts: Int {
        get {
            return userEnteredContracts
        }
        set(newContracts) {
            userEnteredContracts = newContracts
        }
    }
}

Can somebody explain the issue and offer a solution please?

Vee
  • 1,821
  • 3
  • 36
  • 60
  • How did you declare `order` in your view? – pawello2222 Aug 13 '20 at 20:43
  • @pawello2222 - just updated question to show how order was declared. – Vee Aug 13 '20 at 21:01
  • 1
    This is because `quantity` can be nil. So in reality you're trying to do `$order.quantity?.contracts` which is not allowed. How should your app behave if `quality` is nil? Also your code will not compile: `contracts` are of type `Int` but you return `userEnteredContracts` which are of type `Int?`. – pawello2222 Aug 13 '20 at 21:10
  • Thanks, @pawello2222! I had assumed Swift would unwrap `quantity?` but obviously, I was mistaken! And yes, thanks for the pointing out that `contracts` and `userEnteredContracts` data type must match. I've updated the `Order` model such that `var quantity: Quantity` and `Quantity` model such that `var contracts: Int?`. Feel free to post answer so you can get credit. Otherwise, I'm happy to answer the question as well. Thanks for your help! – Vee Aug 14 '20 at 05:13

1 Answers1

1

For your binding to work quantity can't be nil.

In reality instead of:

$order.quantity.contracts

you're trying to do

$order.quantity?.contracts

which is not allowed. How should your Picker behave if quantity is nil?

A solution may be to make quantity non-optional:

struct Order {
    var quantity: Quantity
}

Also note that your code will not compile: contracts are of type Int but you return userEnteredContracts which are of type Int?

You may want to make contracts optional:

struct Quantity: Hashable {
    private var userEnteredContracts: Int?
    var contracts: Int? {
        get {
            return userEnteredContracts
        }
        set(newContracts) {
            userEnteredContracts = newContracts
        }
    }
}

or provide a default value:

struct Quantity: Hashable {
    private var userEnteredContracts: Int?
    var contracts: Int {
        get {
            return userEnteredContracts ?? 0
        }
        set(newContracts) {
            userEnteredContracts = newContracts
        }
    }
}
pawello2222
  • 46,897
  • 22
  • 145
  • 209
  • 1
    Also, if using the picker, I needed to modify the content in the `ForEach` loop from `Text("\(contracts)")` to `Text(String(contracts)).tag(contracts as Int?)`. – Vee Aug 14 '20 at 15:17