Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Getting "ambiguous expression" when try to pass tuple to callback function

I have this class for authenticating a user against my backend.

class BackendService {


class func performLogin(#email: String, password: String, success:((res: NSHTTPURLResponse, json: JSON, statusCode: HTTPStatus))->(), failure: (NSError)->()) {

    let loginURL = baseURL + "/login"
    let parameters = ["email": email, "password": password]

    Alamofire.request(.POST, loginURL, parameters: parameters).responseJSON { (req, res, json, err) in

        if(err != nil) {
            let response = (error: err!)
            failure(response)
        }
        else {


            if let httpStatus = HTTPStatus(rawValue: res!.statusCode) {
                let response = (res: res, json: JSON(json!) , statusCode: httpStatus)
                success(response)
            }
        }
    }

}

In success(response) I am getting Type of expression is ambiguous without more context. Any ideas?

Is there a better, more Swifty way, to write this class?

like image 556
Thanos Avatar asked Jan 15 '15 10:01

Thanos


1 Answers

The reason it wasn't compiling was that you had an extra set of parentheses around the success tuple declaration. If you remove them, then it will compile. Here's an updated version of your function with as few of changes as possible that compiles.

You need to make sure you have baseURL defined somewhere.

class func performLogin(#email: String, password: String, success:(res: NSHTTPURLResponse, json: JSON, statusCode: HTTPStatus)->(), failure: (NSError)->()) {

    let loginURL = baseURL + "/login"
    let parameters = ["email": email, "password": password]

    Alamofire.request(.POST, loginURL, parameters: parameters).responseJSON { (req, res, json, err) in

        if (err != nil) {
            let response = (error: err!)
            failure(response)
        }
        else {
            if let httpStatus = HTTPStatus(rawValue: res!.statusCode) {
                let response = (res: res!, json: JSON(json!), statusCode: httpStatus)
                success(response)
            }
        }
    }
}

Here's an updated version of your original function that is certainly cleaner, but isn't entirely safe yet. A good rule of thumb is the more exclamation marks, the more risk.

typealias LoginSuccessHandler = (NSHTTPURLResponse, JSON, HTTPStatus) -> Void
typealias LoginFailureHandler = (NSError) -> Void

class func performLogin(#email: String, password: String, success: LoginSuccessHandler?, failure: LoginFailureHandler?) {
    let loginURL = baseURL + "/login"
    let parameters = ["email": email, "password": password]

    Alamofire.request(.POST, loginURL, parameters: parameters).responseJSON { request, response, json, error in
        if let error = error {
            failure?(error)
        } else {
            if let httpStatus = HTTPStatus(rawValue: response!.statusCode) {
                success?(response!, JSON(json!), httpStatus)
            }
        }
    }
}

You should really take a look at @mattt's awesome validation logic built into the Alamofire.Request class. That way you could remove the need for the HTTPStatus enumeration altogether.

  • public func validate() -> Self
  • public func validate(contentType array: [String]) -> Self
  • public func validate(statusCode array: [Int]) -> Self
  • public func validate(statusCode range: Range<Int>) -> Self
  • public func validate(validation: Validation) -> Self
like image 119
cnoon Avatar answered Nov 15 '22 03:11

cnoon