Alamofire 4 migration guide

Alamofire 4 Migration Guide
Author: cnoon
translator: kemchenj

Translator note:

The company recently to project the migration to Swift 3, shoving the migration guide Alamofire 4 translation, although before read a part of the source, but still see a lot of new things, I’m going to the new Adapter and Retrier used in the project, I hope everyone can have the harvest after reading.

Text:

Alamofire 4 is a large version of the latest Alamofire update, a Swift iOS, based on tvOS, macOS, HTTP watchOS network library. As a large version of the update, as 4 of the semantic, API introduces some destructive changes.

This guide is designed to help you move from Alamofire 3.x to the latest version of the smooth, but also to explain the new design and structure, as well as functional updates

Requirement

  • IOS 8.0+, macOS 10.10.0+, tvOS 9.0+ and watchOS 2.0+
  • Xcode 8.1+
  • Swift 3.0+

For those who want to use Alamofire in iOS 8 or macOS 10.9, use the latest version of the 3.x version of the release (support for Swift 2.2 and 2.3)

Upgrade benefits

  • The perfect fit Swift 3: follows the new API design specification
  • New error handling system: new AFError mode is added to the new model in SE-0112
  • The new RequestAdapter protocol: can adapt fast and convenient when initializing the Request, for example in the request header to join Authorization
  • The new RequestRetrier protocol: can detect and retry failed Request, and even their own needs to build a set of proven solutions (OAuth1, OAuth2, xAuth, Basic Auth and so on)
  • The new Parameter Encoding protocol replaces the previous ParameterEncoding enumeration, allowing you to expand and customize more easily, and throw exceptions when you are wrong, rather than simply returning a tuple
  • New request types: including DataRequest, DownloadRequest, UploadRequest and StreamRequest, implements a specific schedule, verification and serialization of the API as well as their respective Request types
  • The new schedule API: includes downloadProgress and uploadProgress, support for progress and Int64 types, and will run in the specified thread, default to the main thread
  • More powerful data validation: when validation fails, including data or temporaryURL and destinationURL can be used to transform the closure of the server to return the error information
  • New download address processing: you can get full control, rather than just provide a destinationURL as before, you have to create a temporary folder, delete the previous file
  • New Response type: unified response API, and for all download tasks to provide temporaryURL and downloadURL, as well as other new platform task attributes

API destructive modification

Follow up Alamofire 4 Swift all the 3 modifications, including API design specifications. Therefore, almost all Alamofire API have a certain degree of modification. We can’t put all these modifications listed in the document, so we’ll get the API most commonly used list, and then tell you these are API what changes, but not to those who sometimes help compile error.

Namespace modification

Some of the commonly used classes are moved to the global namespace to become the first class, making them easier to use

  • Manager to SessionManager
  • Request.TaskDelegate to TaskDelegate
  • Request.DataTaskDelegate to DataTaskDelegate
  • Request.DownloadTaskDelegate to DownloadTaskDelegate
  • Request.UploadTaskDelegate to UploadTaskDelegate

We also re adjusted the file structure and organizational model, to help better follow the code, we hope that this will allow more users to understand the internal structure and the specific implementation of Alamofire, but is the power

Generate request

The build request is the most important operation in Alamofire, where there are 3.x and 4 equivalent code comparisons

Data Request – with URL string Simple

3 / / Alamofire Alamofire.request (.GET, urlString) {.Response request, response, data, error in print (request) print (response) print (data) print (error)} / / Alamofire 4 Alamofire.request.Response response in (urlString) {/ / default to `.get` debugPrint (response)}

Data Request – with URL string Complex

Alamofire 3 let parameters: [String: / / AnyObject] = ["foo": "bar" Alamofire.request (.GET, urlString, parameters: parameters, encoding:.JSON).Progress totalBytesRead totalBytesExpectedToRead in {bytesRead, print (Bytes: / Total / Bytes: (bytesRead), (totalBytesRead), Total Bytes (totalBytesExpectedToRead) Expected: /.Validate} ") {request, response in / / custom check closure (access to server data) return.Success.ResponseJSON response in debugPrint} {(response)} / / Alamofire 4 let parameters: Parameters =" foo ":" bar "Alamofire.request (urlString, method:.Get, parameters: parameters, encoding: JSONEncoding .default.DownloadProgress (queue:) DispatchQueue.global (qos:.Utility) progress in (print) {"progress: / (progress.fractionCompleted)")}.Validate {request, response, data, in / / check closure custom, now add the `data` parameter (allows you to convert the data mining to advance to the error message when necessary) return.Success.ResponseJSON response in debugPrint} {(response)}

Download Request – With URL string Simple

3 let destination / / Alamofire = DownloadRequest.suggestedDownloadDestination (Alamofire.download) (.GET, urlString, destination:, destination).Response, response, data {request, error, in / / how to get where fileURL? Print (request) print (response) print (data) print (error)} / / Alamofire 4 let (Alamofire.download) (destination = DownloadRequest.suggestedDownloadDestination urlString, to: destination.Response response in) {/ / default to `.get` print (response.request) print (response.response) print (response.temporaryURL) print (response.destinationURL) print (response.error)}

Download Request – Simple With URLRequest

3 let destination / / Alamofire = DownloadRequest.suggestedDownloadDestination (Alamofire.download) (urlRequest destination: destination).Validate (.ResponseData) {response in / / fileURL where, too difficult to obtain the debugPrint (response)} / / Alamofire 4 Alamofire.download (urlRequest to: destination).Validate (.ResponseData) {response in debugPrint (response) print (response.temporaryURL (print) response.destinationURL})

Download Request – With URL String Complex

3 let fileURL: NSURL let Alamofire / destination: Request.DownloadFileDestination = {in} _ _, fileURL let parameters: [String: AnyObject] = "foo": "bar" Alamofire.download (.GET, urlString, parameters: parameters, encoding:.JSON, to: destination).Progress totalBytesRead, totalBytesExpectedToRead {bytesRead, in print ("Bytes: / Total (bytesRead). Bytes: (totalBytesRead), Total / Bytes / Expected: (totalBytesExpectedToRead).Validate {request}"), response in / / custom check implementation (not obtain temporary position and the target position to download download return.Success.ResponseJSON {response}) in print (fileURL) / / only caught in the closure of the situation Get, not ideal debugPrint (response) let fileURL: URL} / / Alamofire 4 let destination: DownloadRequest.DownloadFileDestination = {_, _ in return (fileURL, [.createIntermediateDirectories,.RemovePreviousFile])} let parameters: Parameters = "foo": "bar" Alamofire.download (urlString, method:.Get, parameters: parameters, encoding: JSONEncoding.default, to: destination).DownloadProgress (queue: DispatchQueue.global (qos:.Utility) progress in (print) {"progress: / (progress.fractionCompleted)")}.Validate {request, response, temporaryURL, destinationURL, in / / check closure custom, now includes fileURL (when necessary to obtain error Return.Success {.ResponseJSON}) information response in debugPrint (response) print (response.temporaryURL) print (response.destinationURL)}

Upload Request – With URL string Simple

3 / / Alamofire Alamofire.upload (.POST, urlString, data: data response,.Response) {request, data, error in print (request) print (response) print (data) print (error)} / / Alamofire 4 Alamofire.upload (data, to: urlString.Response response in) {/ / default to `.post` debugPrint (response)}

Upload Request – Simple With URLRequest

3 / / Alamofire Alamofire.upload (urlRequest, file:).ResponseData (fileURL).Validate in debugPrint (response) {response} / / Alamofire 4 Alamofire.upload (fileURL, with:).ResponseData (urlRequest).Validate in debugPrint (response) {response}

Upload Request – With URL string Complex

3 / / Alamofire Alamofire.upload (.PUT, urlString, file:, fileURL).Progress totalBytes, totalBytesExpected {bytes, in / / here is the schedule to upload or download? ("Bytes: / print (bytesRead), Total Bytes: (totalBytesRead), Total / Bytes / Expected: (totalBytesExpectedToRead) {request}").Validate, response in / / custom check the implementation (not obtain server data) return.Success.ResponseJSON response in debugPrint} {(response)} / / Alamofire 4 (Alamofire.upload fileURL, to: urlString, method:.Put.UploadProgress (queue:) DispatchQueue.global (qos:.Utility) progress in (print) {"upload progress : / (progress.fractionCompleted) ")}.DownloadProgress {progress in / / default in home team called print (" download progress: / (progress.fractionCompleted) ")}.Validate {request, response, data, in / / check closure custom, now add the `data` parameter allows you to convert the data in advance (to dig into the error information when necessary when return.Success.ResponseJSON {response}) in debugPrint (response)}

As you can see, there are many API destructive changes, but the commonly used API or the use of the original design, but now through a line of code to generate more complex request, maintain order and more concise.

URLStringConvertible protocol

There are two small changes to the URLStringConvertible protocol

URLConvertible

The first big “big” change is that URLStringConvertible has been renamed to URLConvertible. in 3.x, which is defined by URLStringConvertible:

Public protocol URLStringConvertible {URLString: String {get}}

Now in Alamofire 4, the URLConvertible protocol is defined:

Public protocol URLConvertible {func () throws -> URL} (asURL)

As you can see, the URLString property is completely removed and replaced with a asURL method that might throw an exception

Alamofire is one of the most common problem is that users forget to sign encoding URL, cause Alamofire to crash. Until now, we (team Alamofire) attitude is Alamofire is so designed, and you must comply with the URL protocol of RFC 2396. But for the community is not so good, because we are more I hope Alamofire told us that URL is not legitimate and not directly crash off.

Now, back to the new URLConvertible protocol. Alamofire cannot safely not string URL standard, in fact is because of the lack of security of URLStringConvertible. Alamofire may not know how you create a legitimate URL. so if URL can’t pass is created by URLConvertible, the exception is a AFError.invalidURL to be thrown.

This modification (as well as many other modifications) allows Alamofire to safely handle an unreasonable URL and throw an exception in the callback

URLRequest Conformance

URLRequest no longer comply with URLStringConvertible, is now an extension of URLConvertible. but it is also just before version of it, is not so important. But this is likely to make Alamofire API ambiguity. Therefore, URLRequest no longer comply with URLStringConvertible.

This means that you can’t do this in your code:

Let urlRequest = URLRequest (url: URL (string: "https://httpbin.org/get")) let urlString = urlRequest.urlString

In Alamofire 4, you should do this:

Let urlRequest = URLRequest (url: URL (string: "https://httpbin.org/get") let urlString = urlRequest.url?.absoluteString

See PR-1505 for more information

URLRequestConvertible

In 3.x, URLRequestConvertible will produce the same ambiguity problem, before the URLRequestConvertible is so defined:

Public protocol URLRequestConvertible {URLRequest: URLRequest {get}}

Now, in Alamofire 4, that’s what it is:

Public protocol URLRequestConvertible {func () throws -> URLRequest} (asURLRequest)

As you can see, the URLRequest property is replaced with the asURLRequest method, and an exception is thrown when the URLRequest fails

This effect is most likely the Router (routing) design for you, if you use Router, then you have to change, but will become better! You need to implement the asURLRequest method will throw an exception when necessary. You no longer need to unpack the mandatory data and parameters, or any construction of a mistake ParameterEncoding. Router now throw in do-catch can be processed by the Alamofire to help you out.

See PR-1505 for more information

new function

Request Adapter (request adapter)

RequestAdapter protocol is a new feature in Alamofire 4

Public protocol RequestAdapter func adapt (urlRequest: URLRequest _ {throws -> URLRequest});

It allows each SessionManager generated Request are generated before parsing and in accordance with the rules of adaptation. A typical scene is using the adapter to request to add a Authorization head.

Class AccessTokenAdapter: RequestAdapter let accessToken: String init {private (accessToken: String) {self.accessToken} = accessToken func adapt (_ urlRequest: URLRequest) throws -> URLRequest urlRequest if urlRequest.urlString.hasPrefix {var = urlRequest ("https://httpbin.org") {urlRequest.setValue ("Bearer + accessToken", "forHTTPHeaderField: Authorization") return urlRequest let sessionManager}}} = SessionManager (sessionManager.adapter) = AccessTokenAdapter (accessToken: 1234) sessionManager.request ("https://httpbin.org/get")

If a Error is generated in the adaptation process, it will be thrown layer by layer, and finally passed to the Request request callback

See PR-1450 for more information

Request Retrier (request reconnection)

RequestRetrier is another new protocol for Alamofire 4

Public typealias RequestRetryCompletion (shouldRetry: Bool = _ _, timeDelay: TimeInterval -> public protocol RequestRetrier; Void) {func (manager: SessionManager retry should _, request: Request, with error: Error, completion: @escaping RequestRetryCompletion)}

It can be restarted when the Request encounters Error, after a specified delay

Class OAuth2Handler: RequestAdapter, RequestRetrier func should (manager: _ {public SessionManager, retry request: Request, with error: Error, completion: RequestRetryCompletion) {if let response = request.task.response as? HTTPURLResponse, response.statusCode = = 401 {completion (true, 1) / / else {completion} second after the retry (false, 0)}} / / not even let sessionManager (SessionManager)} = sessionManager.retrier = (OAuth2Handler) sessionManager.request (urlString).ResponseJSON in debugPrint (response) {response}

Chonglian device allows you to detect Request after completion and completion of all Validation detection and then consider whether to try again. When used in conjunction with RequestAdapter and RequestRetrier, you can give OAuth1, OAuth2, Basic Auth to create a set of calibration system continuously updated (credential refresh systems), and even the rapid retry strategy. The possibilities are endless. Want to get more information about these topics and examples, see README.

Translator’s note: there is no too can understand the meaning of the author, the translation is not good, the
When using directly both the RequestAdapter and RequestRetrier protocols together, you can create credential refresh systems for OAuth1, OAuth2 Basic, Auth and even exponential backoff retry policies. view PR-1391 and PR-1450 for more information.

Task Metrics

In iOS, tvOS 10 and macOS 10.12, Apple introduced a new URLSessionTaskMetrics API, task metrics contains some statistical information request and response, API and Alamofire like Timeline, but provides statistical information not available in many Alamofire. Of these new API very excited, but all this are exposed to every type of Response means that it is not easy to use.

Alamofire.request (urlString).Response {response debugPrint (response.metrics)} (in)

It is important to note that these API can only be used on iOS and tvOS 10+ and macOS 10.12+, so it is dependent on the running device, and you may need to do a feasibility check

Alamofire.request (urlString).Response {in if #available (iOS 10, *) {debugPrint (response.metrics)}}

See PR-1492 for more information

Updated Features update function

Alamofire 4 to strengthen the existing functions and added many new features. This chapter is mainly about over the function update and use. If you want to get more information, please point into the link to view the relevant pull request.

Errors anomaly

Alamofire 4 added a new exception system, using the new model proposed in the proposal SE-0112. The new exception system mainly around the AFError, an inherited Error enumeration type, contains the main case.

  • .invalidURL (url: URLConvertible) – creates a URLConvertible that returns a value of type URL
  • .parameterEncodingFailed (reason: ParameterEncodingFailureReason) – when one of the arguments is coded, an error is thrown and returned
  • .multipartEncodingFailed (reason: MultipartEncodingFailureReason) – multipart encoding error will throw an error and return
  • .responseValidationFailed (reason: ResponseValidationFailureReason) – when called validate () throws an error when it is captured and thrown to the outside
  • .responseSerializationFailed (reason: ResponseSerializationFailureReason) – returns an error when the data is serialized and throws an exception

Each case contains a specific reason for the exception, and the exception is another type of enumeration with specific error messages, which makes it easier for Alamofire to identify the source and cause of the error

Alamofire.request (urlString).ResponseJSON in guard case let {response.Failure (error) response.result = else {return} if let error = error as? AFError switch error {case {.InvalidURL (let URL): Print ("invalid URL: / (URL) - (error.localizedDescription) case /.ParameterEncodingFailed") (let reason): Print ("parameter encoding failure: / (error.localizedDescription) (" print ") (reason) / failure reason:" case.MultipartEncodingFailed (let): Print (reason) Multipart / encoding failure: (error.localizedDescription) ("print") (reason) / failure reason: "case.ResponseValidationFailed (let) reason): Print (" Response / (error.localizedDe check failed: Scription) "(print)" failure reason: / (reason) ") switch reason case.DataFileReadFailed: print {.DataFileNil (" cannot read the download file ") case.MissingContentType (let acceptableContentTypes): Print (" file type "unknown: / (acceptableContentTypes) case.UnacceptableContentType (let) acceptableContentTypes, let (responseContentType): Print file type: / (responseContentType) / (acceptableContentTypes) to read:" case.UnacceptableStatusCode (let) code (print): "request the return status code error: / (code)" case.ResponseSerializationFailed (let)} reason (print): "return to the content request order Column failure: / (error.localizedDescription) "(print)" failure reason: / (reason) "(print)}" / "error: (error.underlyingError) else if let error)} as {print = error? URLError (URL error: / (error)")} else {print ("unknown error: / (error)")}}

A new design approach to you more freedom when you need to reach the most specific error. makes it had to deal with NSError developers around more easily work. By using a custom Error type in Alamofire, we can see the generic parameters of Result and Response was reduced to only one, simplify the return data serialization logic.

See PR-1419 for more information

Parameter Encoding Protocol parameter coding protocol

The ParameterEncoding enumeration type has solved the problem well over the past two years, but we have some limitations when we want to locate in Alamofire 4

  • .url is always a bit confusing, since it is an address defined by the HTTP protocol
  • .urlEncodedInURL and.Url are always confusing, so people can’t tell the difference between them
  • .JSON and.PropertyList encoding can not customize the encoding format or write the way
  • .Custom coding is too difficult for users to master

For these reasons, we decided to remove the Alamofire 4 in this enumeration! Now, ParameterEncoding became a protocol, joined the typedef Parameters to create parameter dictionary for you, and abide by the agreement through the establishment of three encoding structure URLEncoding, JSONEncoding and PropertyList.

Public typealias Parameters [String: Any] public protocol ParameterEncoding = {func (urlRequest: URLRequestConvertible encode _, with parameters: Parameters throws -> URLRequest;}?)

URL Encoding (parameter encoding)

The new URLEncoding structure contains a Destination enumeration that supports three types of object coding

  • .methodDependent – for GET, HEAD and DELETE methods use the query string, while the other HTTP method will be encoded as HTTP body.
  • .queryString – set or add content to existing queryString
  • .httpBody – setting the requested HTTP body content

The encoding format will make it easier for you to control the parameters of the URLRequest encoding. Create the request before and still use the same way, no matter what form of encoding, will remain the same as before, the default behavior.

Let parameters: [Parameters = "foo": "bar" Alamofire.request (urlString parameters:, parameters) / / Encoding => URLEncoding (destination:.MethodDependent); Alamofire.request (urlString, parameters: parameters, encoding: URLEncoding (destination:.QueryString) Alamofire.request (urlString), parameters: parameters, encoding: URLEncoding (destination:.HttpBody) Static convenience properties (we'd) / / like to encourage everyone to use this more concise form) / / static attribute convenience (we want to encourage everyone to use this more concise form of Alamofire.request (urlString), parameters: parameters, encoding: URLEncoding.default Alamofire.request (urlString), parameters: parameters, encoding: URLEncoding.queryString Alamofire.request (urlString, parameter) S: parameters, encoding: URLEncoding.httpBody)

JSON Encoding (JSON code)

The new JSONEncoding structure opens up the interface that allows you to customize the JSON write form

Let parameters: [Parameters = "foo": "bar" Alamofire.request (urlString, parameters: parameters, encoding: JSONEncoding (options: [])) Alamofire.request (urlString, parameters: parameters, encoding: JSONEncoding (options:.PrettyPrinted) Static convenience properties (we'd) / like to encourage everyone to use this more concise form) / / convenience (static attribute we want to encourage everyone to use this more concise form of Alamofire.request (urlString), parameters: parameters, encoding: JSONEncoding.default Alamofire.request (urlString), parameters: parameters, encoding: JSONEncoding.prettyPrinted)

Property List Encoding (attribute list encoding)

The new PropertyListEncoding structure allows custom plist formatting and Writing Options

Let parameters: [Parameters = "foo": "bar" Alamofire.request (urlString, parameters: parameters, encoding: PropertyListEncoding (format:.Xml, options: 0) (Alamofire.request) urlString, parameters: parameters, encoding: PropertyListEncoding (format:.Binary, options: 0)) / / Static convenience properties (we'd like to encourage everyone to use this more concise form) / / static attribute convenience (we want to encourage everyone to use this more concise form of Alamofire.request (urlString), parameters: parameters, encoding: PropertyListEncoding.xml Alamofire.request (urlString), parameters: parameters, encoding: PropertyListEncoding.binary)

Custom Encoding custom coding

Create a custom ParameterEncoding as long as you follow this agreement to create a type. You want to get more examples, please check the following README

See PR-1465 for more information

Request Subclasses (subclass of Request)

In Alamofire 4, request, download, upload and stream API will not return to Request, they will return a specific subclass of Request. The following realistic reasons lead us to make this change and community questions:

  • Progress: progress behavior in upload request will be very confusing. Progress in a upload request to return to what is? Upload progress? Or return to the content download progress? If you are back, then how can we distinguish between them, to know which one end is returned at what time?
  • Response Serializers: returns to data content serialization and upload request design, donwload and stream do not need to request serialization. You need to how to get to the address of the file in the download is complete? ResponseData, responseString and responseJSON for a donwload request and what it means? Stream request?

Alamofire 4 now has four subclasses of Request, and each type has some unique API. so that you can make each subclass is able to customize the specific request types through the establishment of extension.

Open class Request {/ / contains shared attributes, validation, and comply with CustomStringConvertible and CustomDebugStringConvertible methods / / open class DataRequest:} Request {/ / contains data flow (not to be confused with StreamRequest) and the open class method to download progress} DownloadRequest: {/ / Request contains the download location and options, the downloaded data and schedule method class UploadRequest: DataRequest} open {/ / inherits all DataRequest methods, and contains the open class upload progress method StreamRequest:} Request {/ / only inherited Request, currently do not have any custom API}

Through this segmentation, Alamofire is now available for each type of request custom related API. that will cover all possible needs, but let us take the time to take a closer look at how this will change the progress report and download address.

See PR-1455 for more information

Download and Progress Upload (download and upload your progress)

Data, progress report, system download and upload request completely redesigned again. Each type of request contains a closure, whenever a progress update, will call and incoming parameters of type Progress. The closure will be invoked in the specified queue, the default queue based.

Data Request progress

Alamofire.request (urlString.DownloadProgress) {progress in / / default in home team called print ("download progress: / (progress.fractionCompleted)".ResponseJSON in debugPrint response)} {(response)}

Download Request progress

Alamofire.download (urlString, to: destination.DownloadProgress (queue:) DispatchQueue.global (qos:.Utility)) {progress in / /.Utility queue call print ("download progress: / (progress.fractionCompleted)".ResponseJSON in debugPrint response)} {(response)}

Upload Request progress

Alamofire.upload (data, to: urlString, withMethod:.Post.UploadProgress progress in) {/ / default in the home team called print ("upload progress: / (progress.fractionCompleted).DownloadProgress progress in")} {/ / default in home team called print ("download progress: / (progress.fractionCompleted).ResponseData {response}") in debugPrint (response)}

Now it is easy to separate upload request upload and download progress

See PR-1455 for more information

Download File Destinations file download address

In Alamofire 3.x, the successful completion of the download requests will always be in the destination callback to move the temporary file to the final destination folder, which is convenient, but also brings a few restrictions:

  • Forced – API forces you to provide a destination closed package to move files, even if you don’t want to move files after verification
  • Limiting – there is no way to adjust the file system to move files priority. If you need to delete the target folder before before the existence of the file on the mobile? If you need to create a temporary file directory before moving?

These restrictions will be in Alamofire 4 doesn’t exist. The first is the destination closure of optional. Now, destination defaults to nil, means that the file system does not move the file, and will return to a temporary file URL.

Alamofire.download (urlString).ResponseData {response print ("temporary file URL: / in (response.temporaryURL)")}

We will restore the DownloadResponse type, see the Reponse Serializers section for more details

Download Options download options

Another major change is the destination closure add download options, so you can make more file system operations. In order to achieve the purpose, we set up a DownloadOptions type and added to the DownloadFileDestination closure.

Public typealias DownloadFileDestination (temporaryURL: URL = _ _, response: HTTPURLResponse -> (destinationURL:); URL, options: DownloadOptions)

The two DownloadOptions support at this stage is:

  • .createIntermediateDirectories – if you have the specified download address, you will create a directory for the download address
  • .removePreviousFile – if there is a specified download address, it will automatically replace the same file

These two options can be used as follows:

Let destination: DownloadRequest.DownloadFileDestination = {_, _ in return (fileURL, [.removePreviousFile,.CreateIntermediateDirectories], Alamofire.download (urlString, to:)} destination.Response response in debugPrint) {(response)}

If an exception is thrown when the file system is operating, DownloadResponse’s error will be the URLError type

See PR-1462 for more information

Response Validation data validation

There are several areas in Alamofire 4 that can enhance the data validation system:

  • Incoming data in Validation callback closures
  • Request subclasses can customize the data validation system, such as the temporaryURL and destinationURL in the download request exposed to the callback closures

By inheriting the Request, each Request subclass can define a set of data validation closures (typealias) and the requested API.

Data Request data request

DataRequest (UploadRequest’s parent class) exposed Validation is currently defined as:

Extension DataRequest {typealias Validation = (URLRequest, HTTPURLResponse, Data?) -> ValidationResult}

Expose the Data directly in the closure, and you don’t need to add a extension to the Request to access it:

Alamofire.request (urlString).Validate, response, data {request, in guard let data = Data else return.Failure (customError) {} / / 1) to verify the data returned to ensure error / / operation will not the next 2) if the validation fails, you can put the error information back out, even with the custom error return.Success}.Response in debugPrint (response) {response}

Download Request download request

The Validation closure in DownloadRequest is similar to the one in DataRequest, but it’s a lot more customized to download

Extension DownloadRequest {public typealias = Validation (URLRequest, request: _? _ response: HTTPURLResponse, temporaryURL: URL, _ _? DestinationURL: URL? -> ValidationResult);}

The temporaryURL and destinationURL parameters are now so that you can in the closure of direct access to the server to return the data. This allows you to check the downloaded file, when needed can throw a custom error.

Alamofire.download (urlString.Validate) {request, response, temporaryURL, destinationURL in guard let fileURL temporaryURL else {return =.Failure (customError)} do {let = try Data _ (contentsOf: fileURL) return.Success catch.Failure {return}}} {(customError).Response response in debugPrint (response)}

By direct exposure of the data returned from the server in the closure, all exceptions can be Validation closure to capture it, and you can customize the error message. If there is access to information and response serialization callback the same, response can be used to handle the error information rather than simply the logical assignment specific examples here. Please check the following README..

See PR-1461 for more information

Response Serializers returns data serialization

There are several limitations in the serialization system in Alamofire 3.x:

  • The serialized API can be used in download and stream request, but it will lead to the unknown behavior how to get to the file URL in the download success? ResponseData, responseString or responseJSON will produce what kind of behavior in the donwload request in the stream request??
  • Response API returns four parameters rather than packaged into a Response type. The biggest problem is the change of API will lead to any change in front of behavior. In between the serialization and deserialization of API switch can be confusing, and lead to debug compilation errors.

As you can see, this set of Alamofire 3.x serialization system has so many limitations. So, in Alamofire 4, the Request type is first segmentation to each sub class, to do custom serialization, and custom API left a space. Before we understand the serialization mode, we first look at the new the type of Response

Default Data Response

DefaultDataResponse represents not serialized data. Alamofire server returns without any treatment, just to get information from the SessionDelegate and packaged in a structure inside the return.

Public struct DefaultDataResponse public let request: URLRequest {public let response:? HTTPURLResponse? Public let data: Data public let error:? Error? Public var metrics: URLSessionTaskMetrics? _metrics as URLSessionTaskMetrics {return}}?

Here is a return you will get DataRequest.response

Alamofire.request (urlString).Response {response debugPrint (response)} Alamofire.upload (file, to: urlString).Response {response debugPrint in (response)}

Data Response

The generic DataResponse type is the same as the Response in the Alamofire 3.x, but the internal refactoring contains new metrics variables

Public struct DataResponse< Value> let request: {public URLRequest? Public let response: HTTPURLResponse public let data:? Data? Public let result: Result< Value> public let timeline:; Timeline public var metrics: URLSessionTaskMetrics? _metrics as URLSessionTaskMetrics {return}}?

Using DataRequest and UploadRequest, you can use response serialization like API before (3.x)

Alamofire.request (urlString.ResponseJSON) {response in debugPrint (response) print (response.result.isSuccess) Alamofire.upload (fileURL, to:} urlString {response.ResponseData) in debugPrint (response) print (response.result.isSuccess)}

Default Download Response default download request Response type

Because donwload requests to data and upload request is not the same, so Alamofire 4 includes a custom donwload Response type. The DefaultDownloadResponse type represents not serialized return data structure containing all SessionDelegate information.

Public struct DefaultDownloadResponse public let request: URLRequest {public let response:? HTTPURLResponse? Public let temporaryURL: URL public let destinationURL:? URL? Public let resumeData: Data public let error:? Error? Public var metrics: URLSessionTaskMetrics? _metrics as URLSessionTaskMetrics {return}}?

The DefaultDownloadResponse type is returned when the new DownloadRequest.response API is used

Alamofire.download (urlString).Response {response debugPrint (response) print (response.temporaryURL)} (in)}

Download Response

New generic DownloadResponse just like DataResponse, but contains a download request specific information. The DownloadResponse type will be returned in DownloadRequest. These new API also applies to DataRequest, as well as access to the temporary directory URL and target directory url.

Alamofire.download (urlString to: destination).ResponseData in debugPrint (response) {response}.ResponseString {response in}.ResponseJSON {debugPrint (response) response in debugPrint (response)}.ResponsePropertyList {response} in debugPrint (response)

The new serialization API makes it easier to download and serialize files

Custom Response Serializers custom serialization

If you have created a custom serialization, you may want to expand support for data and download requests, as we do API Alamofire serialization. If you decide to do so, can take a closer look at how Alamofire in several Request type shared sequence method, then the implementation of Request wrote on it. This allows us to DRY up logic and avoid duplicate code (Don’t repeat yourself).

See PR-1457 for more information