Search code examples
bindingswiftuioptional-chaining

SwiftUI Picker selection parameter giving "Expression type 'Binding<_>' is ambiguous without more context" error


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?


Solution

  • 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
            }
        }
    }