Josh O'Connor Josh O'Connor - 1 month ago 49
iOS Question

Alamofire error after Swift 3.0 migration: "Cannot convert value of type '(URL, HTTPURLResponse)-> (URL)' to expected argument type 'Parameters'"?

I am currently in the process of updating my codebase to Swift 3.0., and I am using Alamofire. I had to update Alamofire to 4.0 (Alamofire git repo). I have a method to download media (video), and before migration it worked wonderfully. After using Xcode's migration tool I ended up with this error: "Cannot convert value of type '(URL, HTTPURLResponse)-> (URL)' to expected argument type 'Parameters?', which is a [String: Any]. What exactly is this Parameters object and why is it throwing an error? The only difference between this code before migration and now is that now NSURL is replaced by URL. Any help would be wonderful, as I have been stuck on this for the past 3 hours.

let mediaSourceURI: String = media.sourceURI
var filePath: URL?
let destination: (URL, HTTPURLResponse) -> (URL) = {
(temporaryURL, response) in

if let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first, let suggestedFilename = response.suggestedFilename {
filePath = directoryURL.appendingPathComponent("\(suggestedFilename)")
return filePath!
}
return temporaryURL
}

//ERROR BELOW: "destination" is highlighted, and says "Cannot convert value of type '(URL, HTTPURLResponse)-> (URL)' to expected argument type 'Parameters?"
RequestManager.mediaDownloadAlamofireManager.download(mediaSourceURI, method: .get, parameters: destination).response {
(request, response, data, error) -> Void in

self.completeOperation()

}


Here is a link I have been trying to use for reference: Alamofire 4.0 Migration Guide, particularly in the Parameter Encoding Protocol section.

Here is the syntax of the updated download method in Alamofire:
enter image description here

//mediaDownloadAlamofireManager code, which has no errors:

static let mediaDownloadAlamofireManager: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
let serverTrustPolicies: [String: ServerTrustPolicy] = [baseURL : .disableEvaluation]
let manager = SessionManager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
return manager
}()

Answer

 1. Simple Typo

RequestManager.mediaDownloadAlamofireManager.download(mediaSourceURI, method: .get, parameters: destination)

with

RequestManager.mediaDownloadAlamofireManager.download(mediaSourceURI, method: .get, destination: destination)


2. Change in DownloadFileDestination-Type

Alamofire 4.0 changed the type of DownloadFileDestination – the parameter that you call destination. It changed from:

(URL, HTTPURLResponse) -> (URL)

to

(URL, HTTPURLResponse) -> (URL, DownloadRequest.DownloadOptions)

So you also need to change your method to something like this:

let destination: (URL, HTTPURLResponse) -> (URL, DownloadRequest.DownloadOptions) = {
    (temporaryURL, response) in

    if let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first, let suggestedFilename = response.suggestedFilename {
        filePath = directoryURL.appendingPathComponent("\(suggestedFilename)")
        return (filePath!, [.removePreviousFile, .createIntermediateDirectories])
    }
    return (temporaryURL, [.removePreviousFile, .createIntermediateDirectories])
}

Please note that you no longer just return the url, but also have more control over how Alamofire stores files on the file system. Just specify the options you want, such as removePreviousFile or/and createIntermediateDirectories. They are now returned as a Tuple.

Comments