Forward navigation:

Alamofire source learning directory collection

Introduction to the

Alamofire encapsulates all possible errors in the whole network request from the creation of the request to the completion of the response as AFError enumeration objects, and most of the values of the enumeration are enumerated with parameters, even with multi-level parameters. Several sub-enumerations are defined in AFError to represent different types of errors, and AFError is extended. It provides many simple methods and properties, and the entire AFError file has 800+ lines of code, but the whole thing is not hard to understand.

Wrong type

The AFError enumeration lists the error types, most of which take parameters to describe the secondary error types in detail

    Uploadable failed to createUploadable by calling createUploadable(). Enumeration parameter is the cause of error
    case createUploadableFailed(error: Error)
    /// URLRequestConvertible object failed to call the asURLRequest() method to create URLRequest object with argument as the cause of error
    case createURLRequestFailed(error: Error)
    /// SessionDelegate failed to move the downloaded file from the temporary path to the destination path while processing the download request. Parameters are the cause of the error, source path, destination path
    case downloadedFileMoveFailed(error: Error, source: URL, destination: URL)
    /// request cancellation
    case explicitlyCancelled
    /// URLConvertible object failed to call the asURL() method to create the URL object
    case invalidURL(url: URLConvertible)
    /// multiple form parameter encoding failure, parameter is the specific reason for encoding failure, is a defined enumeration type
    case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
    /// The request parameter fails to be encoded using parameterEncoding. ParameterEncoding is the specific reason for the encoding failure and is a defined enumeration type
    case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
    /// parameterEncoder fails to encode request parameters. ParameterEncoder is a defined enumeration type that specifies the specific reason for the encoding failure
    case parameterEncoderFailed(reason: ParameterEncoderFailureReason)
    The adapter failed to process the request. The parameter is the cause of the error
    case requestAdaptationFailed(error: Error)
    /// The RequestRetrier fails to process the request behavior and throws an exception. The parameter is the cause of the error during the retry, the original cause of the request failure
    case requestRetryFailed(retryError: Error, originalError: Error)
    /// If response validation is defined, this error is thrown if the validation fails. The argument is the specific reason for the failure
    case responseValidationFailed(reason: ResponseValidationFailureReason)
    /// An error occurred during serialization of the response data. The argument is the specific reason for the error during serialization
    case responseSerializationFailed(reason: ResponseSerializationFailureReason)
    /// This error will be thrown when the server receives authentication. The parameter is the cause of the authentication failure
    case serverTrustEvaluationFailed(reason: ServerTrustFailureReason)
    /// This error is thrown when the Session is released while the request is still in the ground
    case sessionDeinitialized
    /// The URLSession error is thrown, along with the reason for the URLSession error
    case sessionInvalidated(error: Error?)./// URLSessionTask returns an error
    case sessionTaskFailed(error: Error)
    /// URLRequest validation error, only one possible error: get request with body data
    case urlRequestValidationFailed(reason: URLRequestValidationFailureReason)
Copy the code

In error enumeration, several error parameters have custom enumeration of specific error reasons. You can refine these reasons during error processing.

1. MultipartEncodingFailureReason:

Defines specific reasons for multiple form encoding failures:

    /// The underlying reason the `.multipartEncodingFailed` error occurred.
    public enum MultipartEncodingFailureReason {
        /// The `fileURL` provided for reading an encodable body part isn't a file `URL`.
        case bodyPartURLInvalid(url: URL)
        /// The filename of the `fileURL` provided has either an empty `lastPathComponent` or `pathExtension.
        case bodyPartFilenameInvalid(in: URL)
        /// The file at the `fileURL` provided was not reachable.
        case bodyPartFileNotReachable(at: URL)
        /// Attempting to check the reachability of the `fileURL` provided threw an error.
        case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
        /// The file at the `fileURL` provided is actually a directory.
        case bodyPartFileIsDirectory(at: URL)
        /// The size of the file at the `fileURL` provided was not returned by the system.
        case bodyPartFileSizeNotAvailable(at: URL)
        /// The attempt to find the size of the file at the `fileURL` provided threw an error.
        case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
        /// An `InputStream` could not be created for the provided `fileURL`.
        case bodyPartInputStreamCreationFailed(for: URL)
        /// An `OutputStream` could not be created when attempting to write the encoded data to disk.
        case outputStreamCreationFailed(for: URL)
        /// The encoded body data could not be written to disk because a file already exists at the provided `fileURL`.
        case outputStreamFileAlreadyExists(at: URL)
        /// The `fileURL` provided for writing the encoded body data to disk is not a file `URL`.
        case outputStreamURLInvalid(url: URL)
        /// The attempt to write the encoded body data to disk failed with an underlying error.
        case outputStreamWriteFailed(error: Error)
        /// The attempt to read an encoded body part `InputStream` failed with underlying system error.
        case inputStreamReadFailed(error: Error)}Copy the code

And extends the enumeration to add computed attributes that can quickly get request urls and potential Error objects:

extension AFError.MultipartEncodingFailureReason {
    var url: URL? {
        switch self {
        case let .bodyPartURLInvalid(url),
             let .bodyPartFilenameInvalid(url),
             let .bodyPartFileNotReachable(url),
             let .bodyPartFileIsDirectory(url),
             let .bodyPartFileSizeNotAvailable(url),
             let .bodyPartInputStreamCreationFailed(url),
             let .outputStreamCreationFailed(url),
             let .outputStreamFileAlreadyExists(url),
             let .outputStreamURLInvalid(url),
             let .bodyPartFileNotReachableWithError(url, _),
             let .bodyPartFileSizeQueryFailedWithError(url, _) :return url
        case .outputStreamWriteFailed,
             .inputStreamReadFailed:
            return nil}}var underlyingError: Error? {
        switch self {
        case let .bodyPartFileNotReachableWithError(_, error),
             let .bodyPartFileSizeQueryFailedWithError(_, error),
             let .outputStreamWriteFailed(error),
             let .inputStreamReadFailed(error):
            return error
        case .bodyPartURLInvalid,
             .bodyPartFilenameInvalid,
             .bodyPartFileNotReachable,
             .bodyPartFileIsDirectory,
             .bodyPartFileSizeNotAvailable,
             .bodyPartInputStreamCreationFailed,
             .outputStreamCreationFailed,
             .outputStreamFileAlreadyExists,
             .outputStreamURLInvalid:
            return nil}}}Copy the code

2.ParameterEncodingFailureReason

Defines why request parameters fail to be encoded using the ParameterEncoding protocol object. Enumerations are also extended to quickly retrieve potential Error parameters

    /// The underlying reason the `.parameterEncodingFailed` error occurred.
    public enum ParameterEncodingFailureReason {
        /// The `URLRequest` did not have a `URL` to encode.
        case missingURL
        /// JSON serialization failed with an underlying system error during the encoding process.
        case jsonEncodingFailed(error: Error)
        /// Custom parameter encoding failed due to the associated `Error`.
        case customEncodingFailed(error: Error)}Copy the code

3.ParameterEncoderFailureReason

Defines the request parameters using the ParameterEncoder protocol object coding the cause of the failure, similar ParameterEncodingFailureReason

    public enum ParameterEncoderFailureReason {
        /// Possible missing components.
        public enum RequiredComponent {
            /// The `URL` was missing or unable to be extracted from the passed `URLRequest` or during encoding.
            case url
            /// The `HTTPMethod` could not be extracted from the passed `URLRequest`.
            case httpMethod(rawValue: String)}/// A `RequiredComponent` was missing during encoding.
        case missingRequiredComponent(RequiredComponent)
        /// The underlying encoder failed with the associated error.
        case encoderFailed(error: Error)}Copy the code

4.ResponseValidationFailureReason

The specific cause of failure of validity detection of response data is defined

    /// The underlying reason the `.responseValidationFailed` error occurred.
    public enum ResponseValidationFailureReason {
        /// The data file containing the server response did not exist.
        case dataFileNil
        /// The data file containing the server response at the associated `URL` could not be read.
        case dataFileReadFailed(at: URL)
        /// The response did not contain a `Content-Type` and the `acceptableContentTypes` provided did not contain a
        /// wildcard type.
        case missingContentType(acceptableContentTypes: [String])
        /// The response `Content-Type` did not match any type in the provided `acceptableContentTypes`.
        case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
        /// The response status code was not acceptable.
        case unacceptableStatusCode(code: Int)
        /// Custom response validation failed due to the associated `Error`.
        case customValidationFailed(error: Error)}Copy the code

The extension adds the convenient calculation attribute, which can quickly get the contentType of the request accepted, the contentType of the response returned, the response status code, the potential Error object, etc


extension AFError.ResponseValidationFailureReason {
    var acceptableContentTypes: [String]? {
        switch self {
        case let .missingContentType(types),
             let .unacceptableContentType(types, _) :return types
        case .dataFileNil,
             .dataFileReadFailed,
             .unacceptableStatusCode,
             .customValidationFailed:
            return nil}}var responseContentType: String? {
        switch self {
        case let .unacceptableContentType(_, responseType):
            return responseType
        case .dataFileNil,
             .dataFileReadFailed,
             .missingContentType,
             .unacceptableStatusCode,
             .customValidationFailed:
            return nil}}var responseCode: Int? {
        switch self {
        case let .unacceptableStatusCode(code):
            return code
        case .dataFileNil,
             .dataFileReadFailed,
             .missingContentType,
             .unacceptableContentType,
             .customValidationFailed:
            return nil}}var underlyingError: Error? {
        switch self {
        case let .customValidationFailed(error):
            return error
        case .dataFileNil,
             .dataFileReadFailed,
             .missingContentType,
             .unacceptableContentType,
             .unacceptableStatusCode:
            return nil}}}Copy the code

5.ResponseSerializationFailureReason

Defines the specific reasons for the serialization failure of the response, including the serialization failure to string, JSON, and decodable, or the serialization failure to user-defined types.

    /// The underlying reason the response serialization error occurred.
    public enum ResponseSerializationFailureReason {
        /// The server response contained no data or the data was zero length.
        case inputDataNilOrZeroLength
        /// The file containing the server response did not exist.
        case inputFileNil
        /// The file containing the server response could not be read from the associated `URL`.
        case inputFileReadFailed(at: URL)
        /// String serialization failed using the provided `String.Encoding`.
        case stringSerializationFailed(encoding: String.Encoding)
        /// JSON serialization failed with an underlying system error.
        case jsonSerializationFailed(error: Error)
        /// A `DataDecoder` failed to decode the response due to the associated `Error`.
        case decodingFailed(error: Error)
        /// A custom response serializer failed due to the associated `Error`.
        case customSerializationFailed(error: Error)
        /// Generic serialization failed for an empty response that wasn't type `Empty` but instead the associated type.
        case invalidEmptyResponse(type: String)}Copy the code

The extension adds the string encoding used to get the serialization to string Error, as well as the potential Error object

extension AFError.ResponseSerializationFailureReason {
    var failedStringEncoding: String.Encoding? {
        switch self {
        case let .stringSerializationFailed(encoding):
            return encoding
        case .inputDataNilOrZeroLength,
             .inputFileNil,
             .inputFileReadFailed(_),
             .jsonSerializationFailed(_),
             .decodingFailed(_),
             .customSerializationFailed(_),
             .invalidEmptyResponse:
            return nil}}var underlyingError: Error? {
        switch self {
        case let .jsonSerializationFailed(error),
             let .decodingFailed(error),
             let .customSerializationFailed(error):
            return error
        case .inputDataNilOrZeroLength,
             .inputFileNil,
             .inputFileReadFailed,
             .stringSerializationFailed,
             .invalidEmptyResponse:
            return nil}}}Copy the code

6.ServerTrustFailureReason

Defines the specific cause of server authentication failure, and internally defines the structure of server authentication information, which is returned as the specific cause parameter of the error

    /// Underlying reason a server trust evaluation error occurred.
    public enum ServerTrustFailureReason {
        /// The output of a server trust evaluation.
        public struct Output {
            /// The host for which the evaluation was performed.
            public let host: String
            /// The `SecTrust` value which was evaluated.
            public let trust: SecTrust
            /// The `OSStatus` of evaluation operation.
            public let status: OSStatus
            /// The result of the evaluation operation.
            public let result: SecTrustResultType

            /// Creates an `Output` value from the provided values.
            init(_ host: String._ trust: SecTrust._ status: OSStatus._ result: SecTrustResultType) {
                self.host = host
                self.trust = trust
                self.status = status
                self.result = result
            }
        }

        /// No `ServerTrustEvaluator` was found for the associated host.
        case noRequiredEvaluator(host: String)
        /// No certificates were found with which to perform the trust evaluation.
        case noCertificatesFound
        /// No public keys were found with which to perform the trust evaluation.
        case noPublicKeysFound
        /// During evaluation, application of the associated `SecPolicy` failed.
        case policyApplicationFailed(trust: SecTrust, policy: SecPolicy, status: OSStatus)
        /// During evaluation, setting the associated anchor certificates failed.
        case settingAnchorCertificatesFailed(status: OSStatus, certificates: [SecCertificate])
        /// During evaluation, creation of the revocation policy failed.
        case revocationPolicyCreationFailed
        /// `SecTrust` evaluation failed with the associated `Error`, if one was produced.
        case trustEvaluationFailed(error: Error?)./// Default evaluation failed with the associated `Output`.
        case defaultEvaluationFailed(output: Output)
        /// Host validation failed with the associated `Output`.
        case hostValidationFailed(output: Output)
        /// Revocation check failed with the associated `Output` and options.
        case revocationCheckFailed(output: Output, options: RevocationTrustEvaluator.Options)
        /// Certificate pinning failed.
        case certificatePinningFailed(host: String, trust: SecTrust, pinnedCertificates: [SecCertificate], serverCertificates: [SecCertificate])
        /// Public key pinning failed.
        case publicKeyPinningFailed(host: String, trust: SecTrust, pinnedKeys: [SecKey], serverKeys: [SecKey])
        /// Custom server trust evaluation failed due to the associated `Error`.
        case customEvaluationFailed(error: Error)}Copy the code

The extension adds a quick way to get server authentication information, and possibly Error data

extension AFError.ServerTrustFailureReason {
    var output: AFError.ServerTrustFailureReason.Output? {
        switch self {
        case let .defaultEvaluationFailed(output),
             let .hostValidationFailed(output),
             let .revocationCheckFailed(output, _) :return output
        case .noRequiredEvaluator,
             .noCertificatesFound,
             .noPublicKeysFound,
             .policyApplicationFailed,
             .settingAnchorCertificatesFailed,
             .revocationPolicyCreationFailed,
             .trustEvaluationFailed,
             .certificatePinningFailed,
             .publicKeyPinningFailed,
             .customEvaluationFailed:
            return nil}}var underlyingError: Error? {
        switch self {
        case let .customEvaluationFailed(error):
            return error
        case let .trustEvaluationFailed(error):
            return error
        case .noRequiredEvaluator,
             .noCertificatesFound,
             .noPublicKeysFound,
             .policyApplicationFailed,
             .settingAnchorCertificatesFailed,
             .revocationPolicyCreationFailed,
             .defaultEvaluationFailed,
             .hostValidationFailed,
             .revocationCheckFailed,
             .certificatePinningFailed,
             .publicKeyPinningFailed:
            return nil}}}Copy the code

7.URLRequestValidationFailureReason

There is only one possibility that a get request with the body argument will throw the error and return the body’s data

    /// The underlying reason the `.urlRequestValidationFailed`
    public enum URLRequestValidationFailureReason {
        /// URLRequest with GET method had body data.
        case bodyDataInGETRequest(Data)}Copy the code

Tools extension

AFError defines a number of tool extensions to simplify operations

1. The Error extension adds methods to quickly convert to type AFError

extension Error {
    /// Returns optional AFError, if self is of type AFError, returns optional object, otherwise returns nil
    public var asAFError: AFError? {
        self as? AFError
    }

    /// Return an optional AFError object. If self is not of type AFError, throw an exception with the argument. Note that message is an automatic closure
    public func asAFError(orFailWith message: @autoclosure() - >String.file: StaticString = #file, line: UInt = #line) -> AFError {
        guard let afError = self as? AFError else {
            fatalError(message(), file: file, line: line)
        }
        return afError
    }

    /// Returns an optional AFError object. If self is not of type AFError, a default AFError object is created using the parameter automatic closure
    func asAFError(or defaultAFError: @autoclosure() - >AFError) -> AFError {
        self as? AFError ?? defaultAFError()
    }
}
Copy the code

2. Convenient Bool

The AFError extension defines a number of Bool evaluation attributes for isXXXError to quickly identify error types

3. Convenient attribute acquisition

The AFError extension adds computed properties that can return a variety of parameter types, all of which return optional types. If the type is correct, the corresponding optional type will be returned. Otherwise, nil will be returned. In addition, convenient attribute acquisition is added for enumeration of specific causes of errors

4. Misdescribe extensions

The AFError extension implements the LocalizedError protocol, adding the errorDescription attribute to return an English errorDescription string. Internal enumeration of error causes, all extended to add localizedDescription attribute, used to return the text description of the error,

use

In the use of Alamofire, can throw an exception method, can directly do catch to catch the thrown type, in the use of asAFError conversion into AFError type, and then deal with the specific error type.