Ackman
Ackman

Reputation: 1592

how to represent nil Error Swift completion block

Hi I have a web service worker object in swift that passes a completion block to the caller view controller. The code is as follows:

func getFlightData(for airportCode: String, minutesBehind:String, minutesAhead:String, completion: (([Flight], NSError) -> Void)?) {
    var urlComponents = URLComponents()
    urlComponents.scheme = "https"
    urlComponents.host = "xxxxxxx.com"
    urlComponents.path = "/1/airports/"+airportCode+"/flights/flightInfo"
    urlComponents.queryItems = [
        URLQueryItem(name: "city", value: airportCode),
        URLQueryItem(name: "minutesBehind", value: minutesBehind),
        URLQueryItem(name: "minutesAhead", value: minutesAhead)

    ]

    guard let url = urlComponents.url else { fatalError("Could not create URL from components") }
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.setValue("xxxxxxxxx", forHTTPHeaderField: "Authorization")
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)


    let task = session.dataTask(with: request) { (responseData, response, responseError) in
        DispatchQueue.main.async {


            if let error = responseError {

                //completion block???


            }

            else if let jsonData = responseData {

                let decoder = JSONDecoder()

                do {
                    let posts = try decoder.decode([Flight].self, from: jsonData)
                    //completion?(posts, nil) ???? what to pass for Error? Successful call
                } catch {
                    self.showError()

                }
            }

            else {
                //completion block???
                self.showError()
            }
        }
    }
    task.resume()
}

whatvalues do I pass in the completion blocks Error parameter when call is successful. I cant pass nil as swift does not let me do that. Can someone suggest a better way to make this API call? How to send completion block etc.

Upvotes: 0

Views: 1422

Answers (2)

Charles Srstka
Charles Srstka

Reputation: 17050

Declare the completion block as taking an Error? instead of an NSError, and then you will be able to pass nil to it in the success case. The ? is what makes the parameter optional, which makes it possible for it to contain nil. (Also, use Error instead of NSError, as it is the idiomatic Swift error type).

Alternatively, you can have your completion block take a Result enum, which you can define like this:

public enum Result<T> {
    case success(T)
    case error(Error)

    public func unwrap() throws -> T {
        switch self {
        case let .success(ret):
            return ret
        case let .error(error):
            throw error
        }
    }
}

You can then use either the .success or .error cases, depending on whether the operation succeeded or failed.

Upvotes: 1

GIJOW
GIJOW

Reputation: 2343

It doesn't accept nil because your parameter NSError isn't optional.

Declare you method signature like

func getFlightData(for airportCode: String, minutesBehind:String, minutesAhead:String, completion: (([Flight], NSError?) -> Void)?) {

....

}

And it should work

Upvotes: 0

Related Questions