This is the 14th day of my participation in the August More Text Challenge

I spent the last two days reading Moya, a framework for encapsulating network requests based on Alamofire. Here are my reading notes.

RangeExpression

Here is the filter method for filtering network states:

func filter<R: RangeExpression> (statusCodes: R) throws -> Response where R.Bound = = Int {
    guard statusCodes.contains(statusCode) else {
        throw MoyaError.statusCode(self)}return self
}
Copy the code

RangeExpression is used when representing the range of statusCodes that can be received.

There are several types for representing ranges in Swift:

  • Range: The element type requirements are metComparable
    • Half Range: For example0.. The < 10;
    • Close range: for example0... 10;
  • Countable ranges, in contrast to ranges, have element types that need to be followedStrideableProtocol (integer step size) :
    • Countably half open range (CountableRange) :. Such as0.. The < 10.
    • Countably closed range (CountableClosedRange) :. Such as0... 10.
  • Partial range: refers to the partial range. 或 ..<The range constructed when used as a pre – or post-operator:
    • .As a postposition, for exampleCharacter("a")...
    • .As a precursor, for example. Character("z")
    • ..<As a postposition, for example. The < 10
    • ..<As a precursor, for example10.. <

The eight types above all comply with the RangeExpression protocol.

Label statement — end prematurelyLooping statementsandConditional statements

In the Response class in Moya, there is a code that uses the tag statement:

let jsonData: Data
        
keyPathCheck: if let keyPath = keyPath {
    guard let jsonObject = (try mapJSON(failsOnEmptyData: failsOnEmptyData) as? NSDictionary)?.value(forKeyPath: keyPath) else {
        if failsOnEmptyData {
            throw MoyaError.jsonMapping(self)}else {
            jsonData = data
            break keyPathCheck
        }
    }

    if let data = try serializeToData(jsonObject) {
        jsonData = data
    } else {
        // Omit some code}}else {
    jsonData = data
}

// Omit the following operations on jsonData
Copy the code

In loops, the break statement is often used to terminate the loop prematurely.

In both Swift loop and conditional statements, the break + label statement can be used to prematurely terminate their execution. The code above is a good example of using the break keyPathCheck in the if condition when the if statement needs to be terminated prematurely and the following is executed. If the break + tag is not used here, subsequent operations on jsonData will have duplicate code.

Using breaks simplifies code, and inevitably makes it harder to read.

To avoid duplicate code, there are other ways:

  • Pull out the code and add an instance method;
  • Define a method or closure directly inside the method to handle similar logic.

Add a “parent” to an enum

The core Moya class MoyaProvider is defined as follows:

open class MoyaProvider<Target: TargetType> :MoyaProviderType {}Copy the code

When initializing the MoyaProvider, specify the specific type of the generic Target. The TargetType protocol is implemented using the enum type. If we need to split network requests into modules and put them into different enumerations, why should Target be specified?

If we implement the TargetType protocol using a class, we can create a parent class and specify the parent class type. However, enumeration (enum) types cannot be inherited.

Moya’s solution is MultiTarget:

public enum MultiTarget: TargetType {

    /// The embedded `TargetType`.
    case target(TargetType)


    /// Initializes a `MultiTarget`.
    public init(_ target: TargetType) {
        self = MultiTarget.target(target)
    }
    
    // Omit some code
}
Copy the code

The MultiTarget design is very simple. It simply saves the target: TargetType passed in for initialization and implements the TargetType protocol with target. It achieves the polymorphism of the class (I can’t explain MultiTarget’s design pattern) :

  1. MultiTargetSpecific representation by incomingtargetIs responsible for, similar to how a subclass overrides its parent class;
  2. MultiTargetSimilar to the “parent class”, provides a unified interface externally.

If the expression is not accurate, welcome to correct, thank you.

reference

  • Swift, advanced
  • Swift-label statement