Ambiguous reference to member 'subscript' on Dictionary
Asked Answered
M

1

11

I am trying to create a failable initializer for a class. My class will be initialized using input from a network request. Networks being unreliable, I want to create an initializer the checks for the presence on all properties, and for it to fail otherwise.

I am trying to make use of guard here, so please feel free to point any obvious mistakes in the approach:

public class JobModel {
    let jobId: String
    let status: String
    let toName: String
    let toAddress: String
    let description: String
    let fee: Int
    let jobDate: NSDate
    let fromName: String
    let fromAddress: String

    init?(job: [String:AnyObject]) throws {
        guard self.jobId = job["jobid"] as! String else {
            throw InitializationError.MissingJobId
        }

    }
}

The guard self.jobId line is failing to compile, with error: Ambiguous reference to member 'subscript'

Any ideas on how to correct this error?

Meaganmeager answered 13/11, 2015 at 9:53 Comment(4)
Do you want to fail (i.e. return nil) or throw an error if the property is not present? That's two different things.Kastroprauxel
The error message seems to be misleading: The expression after the guard statement must have an boolean result or the evaluation result of an optional binding (let syntax). Consider to validate the input dictionary before calling the initializer.Banish
@MartinR, I would prefer to throw an error, as the caller of the initialiser will know why the initialisation failed, context that the caller won't get by returning nil.Meaganmeager
All stored properties of a class instance must be initialized before throwing from an initializer. So I agree with @Banish about this, in your case it would be more convenient to validate input before creating the instance.Schechter
A
8

guard requires a condition that conforms to BooleanType. Simple assignment doesn't. You would need something like this.

guard let j = job["jobid"] as? String else {
    throw InitializationError.MissingJobId
}
self.jobId = j

However, then you'll get the error "all stored properties of a class instance must be initialized before throwing from an initializer." This is expected and documented in the The Swift Programming Language:

For classes, however, a failable initializer can trigger an initialization failure only after all stored properties introduced by that class have been set to an initial value and any initializer delegation has taken place.

Chris Lattner mentions the current behavior is undesirable here: http://swift-language.2336117.n4.nabble.com/Swift-2-throwing-in-initializers-td439.html

Arpent answered 13/11, 2015 at 12:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.