Moya latest version 11.0.2

As I wrote this article some time ago, the latest version of Moya has been updated, so the usage has been updated. I have used it, so I specially present the latest use demo for reference. Moya11.0.2 Demo

Moya introduction

Moya is the missing network layer in your app. Instead of wondering where (or how) to place your network requests, Moya manages them for you.

Moya has several nice features:

  • Check for correct API endpoint access at compile time.

  • Allows you to define different endpoint enumeration values for their respective purposes more clearly.

  • Improve testing status to make unit testing easier.

Swift we use Alamofire for the network library. Moya encapsulates another layer on the basis of Alamofire. The following flow chart illustrates the simple working flow chart of Moya:

Moya official download address point I powerful Moya, there are specific use methods in the demo.

This article mainly introduces the usage of Moya

  • Sets the request header information
  • Setting timeout
  • Custom plug-in
  • Self-signed certificate

Note: NetAPIManager (** GitHub**) is the same type of file as NetAPIManager (** GitHub**), which implements the protocol TargetType. Parameter, method, computational properties, and so on, all we need to do is implement these things, of course, we don’t need to implement default values, but setting the header and timeout will change the system default Settings.

For a better view, paste the contents of the NetAPIManager file

// // netapimager. swift // NN110 // // Created by Yihai Chen on 2017/5/12. // Copyright © 2017 Yihai Chen. All rights reserved. // import Foundation import Moya enum NetAPIManager {case Show
    case upload(bodyData: Data)
    case download
    caserequest(isTouch: Bool, body: Dictionary<String, Any>? ,isShow: Bool)} extension NetAPIManager: TargetType {var baseURL: URL {case .request( _, _, _):
            return URL(string: "https://www.pmphmall.com")!
        default:
            return URL(string: "https://httpbin.org")! }} var path: String {// Specify the path of a method.case .Show:
            return ""
        case .upload(_):
            return ""
        case .request(_, _, _):
            return "/app/json.do"
        case .download:
            return ""}} var method: moya. method {// request method get or post type switch self {case .Show:
            return .get
        case .request(_, _, _):
            return .post
        default:
            return.post } } var parameters: [String: Any]? {// Request get post to server parameter switch self {case .Show:
            return nil
        case .request(_, _, _):
            return ["msg":"H4sIAAAAAAAAA11SSZJFIQi7EqPAEgTvf6TP62W7sMoSQhKSWDrs6ZUKVWogLwYV7RjHFBZJlNlzloN6LVqID4a+puxqRdUKVNLwE1TRcZIC/fjF2rPotuX mb84r1gMXbiASZIZbhQdKEewJlz41znDkujCHuQU3dU7G4/PmVRnwArMLXukBv0J23XVahNO3VX35wlgce6TLUzzgPQJFuHngAczl6VhaNXpmRLxJBlMml6g dLWiXxTdO7I+iEyC7XuTirCQXOk4dotgArgkH/InxVjfNTnE/uY46++hyAiLFuFL4cv1Z8WH5DgB2GnvFXMh5gm53Tr13vqqrEYtcdXfkNsMwKB+9sAQ77gr NJmquFWOhfXA/DELlMB0KKFtHOc/ronj1ml+Z7qas82L3VWiCVQ+HEitjTVzoFw8RisFN/jJxBY4awvq427McXqnyrfCsl7oeEU6wYgW9yJtj1lOkx0ELL5F w4z071NaVzRA9ebxWXkFyothgbB445cpRmTC+//F73r1kOyQ3lTpec12XNDR00nnq5/YmJItW3+w1z27lSOLqgVctrxG4xdL9WVPdkH1tkiZ/pUKBGhADAAA ="]
        default:
            returnNil}} var sampleData: Data {// Encode escapereturn "{}".data(using: String.Encoding.utf8)! } var task: task {switch self {case let .upload(data):
        return .upload(.multipart([MultipartFormData(provider: .data(data), name: "file", fileName: "gif.gif", mimeType: "image/gif")]))
            
        default:
            return.request}} var parameterEncoding: parameterEncoding switch self {case .request(_, _, _):
            return URLEncoding.default
        default:
            returnUrlencoding. default} // The following two parameters are written by me to control whether the operation is allowed during network loading and whether to display the loading prompt. Var Touch will be used for these two parameters in the custom plug-in: Bool {// Switch self {case .request(let isTouch, _, _):
            return isTouch
        default:
            return false}} var show: Bool {switch self {case .request( _, _,let isShow):
            return isShow
        default:
            return false}}}Copy the code

How to set upMoyaRequest header information

The setting of header information is very important in the development process, such as server generated token, user unique identifier, etc. We directly on the code, not so much theoretical things, haha

// MARK: - Sets the request header informationlet myEndpointClosure = { (target: NetAPIManager) -> Endpoint<NetAPIManager> in
    
    
    let url = target.baseURL.appendingPathComponent(target.path).absoluteString
    letendpoint = Endpoint<NetAPIManager>( url: url, sampleResponseClosure: { .networkResponse(200, target.sampleData) }, method: target.method, parameters: target.parameters, parameterEncoding: Target.parameterencoding) // Set your HTTP header herereturn endpoint.adding(newHTTPHeaderFields: [
        "Content-Type" : "application/x-www-form-urlencoded"."ECP-COOKIE" : ""])}Copy the code

How do I set the request timeout

// MARK: - Sets the request timeoutlet requestClosure = { (endpoint: Endpoint<NetAPIManager>, done: @escaping MoyaProvider<NetAPIManager>.RequestResultClosure) in
    
    guard var request = endpoint.urlRequest else { return} request.timeoutInterval = 30 // Set the request timeout perioddone(.success(request))
}
Copy the code

Custom plug-in

Custom plug-ins must have the PluginType protocol methods willSend and didReceive

/ / / / / / MyNetworkActivityPlugin swift NN110 / / / / Created by Chen also on 2017/5/10 sea. / / Copyright © 2017 CocoaPods. All rights reserved. // import Foundation import Result import Moya /// Network activity change notification type. public enum MyNetworkActivityChangeType {case began, ended
}

/// Notify a request's network activity changes (request begins or ends). public final class MyNetworkActivityPlugin: PluginType { public typealias MyNetworkActivityClosure = (_ change: MyNetworkActivityChangeType, _ target: TargetType) -> Void let myNetworkActivityClosure: MyNetworkActivityClosure public init(newNetworkActivityClosure: @escaping MyNetworkActivityClosure) { self.myNetworkActivityClosure = newNetworkActivityClosure } // MARK: Plugin /// Called by the provider as soon as the request is about to start public func willSend(_ request: RequestType, target: TargetType) { myNetworkActivityClosure(.began,target) } /// Called by the provider as soon as a response arrives, even if the request is cancelled. public func didReceive(_ result: Result
      
       , target: TargetType) { myNetworkActivityClosure(.ended,target) } }
      ,>Copy the code

Use the custom plug-in approach

// MARK: - Custom web prompt request plug-inlet myNetworkPlugin = MyNetworkActivityPlugin { (state,target) in
    if state == .began {
        //        SwiftSpinner.show("Connecting...")
        
        let api = target as! NetAPIManager
        if api.show {
            print("I can write a load prompt here.")}if! api.touch {print("Well, I can say here forbid user action, wait for the request to end.")}print("I started asking \(api.touch)")
        
        UIApplication.shared.isNetworkActivityIndicatorVisible = true
    } else {
        //        SwiftSpinner.show("request finish...")
        //        SwiftSpinner.hide()
        print("I end my request.")
        UIApplication.shared.isNetworkActivityIndicatorVisible = false}}Copy the code

Self-signed certificate

At WWDC 2016, Apple has stated that starting January 1, 2017, ** all new apps submitted must use HTTPS protocol to make web requests. ** Non-HTTPS network access is disabled by default and it is no longer possible to bypass the ATS(App Transport) by simply adding NSAllowsArbitraryLoads to info.plist Security) (otherwise must be stated during application review and will likely be rejected). So companies that have not yet done so need to move to HTTPS as soon as possible. This article will briefly describe HTTPS and the principle of configuring digital certificates and explain the configuration examples and problems, hoping to help you. (than heart ~)

  1. One is the certificate purchased from an authoritative authority. When the server uses this certificate, the Apple system has its trusted signature root certificate built-in, so the client does not need additional configuration. To ensure certificate security, when a certificate issuer publishes a certificate, the fingerprint algorithm of the certificate is encrypted and published together with the certificate to prevent others from forging a digital certificate. The certificate authority uses its own private key to encrypt its fingerprint algorithm, which can be decrypted by the institutional signature root certificate built into the operating system to ensure the security of the certificate.
  2. The other is a self-signed certificate. The advantage is that you don’t have to buy it, but you can’t be trusted with this certificate, so you need to configure it as a trust certificate in your code.

Specific implementation of self-signed certificate: When we use self-signed certificate to achieve HTTPS request, unlike the certificate issued by the institution, its signed root certificate has been built in the system, so we need to build our server’s signed root certificate in App to verify the digital certificate. First, add the. Cer root certificate generated by the server to the project. Note that you must check targets before adding the certificate. One caveat here: Apple’s ATS requires server support for TLS 1.2 or above; A password that supports forward secrecy must be used; The certificate must be signed using the SHA-256 or better signed hash algorithm. If the certificate is invalid, the connection will fail. Because I signed when I was in generating the root certificate of the hash algorithm is lower than the requirement, after configuration request has been submitted to the NSURLErrorServerCertificateUntrusted = 1202 error, hope you can take note.

So how to use self-signed certificates in Moya to implement HTTPS network requests, please look forward to my next special share…… You need to customize a Manager management

The method of comprehensive use is as follows

Define a commonMoyaRequest service object

let MyAPIProvider = MoyaProvider<NetAPIManager>(endpointClosure: myEndpointClosure,requestClosure: requestClosure, plugins: [NetworkLoggerPlugin(verbose: true, responseDataFormatter: JSONResponseDataFormatter), myNetworkPlugin]) / / MARK: - create a Moya request func the sendRequest (_ postDict: Dictionary<String, Any>? = nil, success:@escaping (Dictionary<String, Any>)->(), failure:@escaping (MoyaError)->()) -> Cancellable? {let request = MyAPIProvider.request(.Show) { result in    
        switch result {
        case let .success(moyaResponse):
            
            
            do {
                let any = try moyaResponse.mapJSON()
                let data =  moyaResponse.data
                let statusCode =  moyaResponse.statusCode
                MyLog("\(data) --- \(statusCode) ----- \(any)")
                
                success(["":""])
                

            } catch {
                
            }
            
           
            
        case let .failure(error):
            
            print(error)
            failure(error)
        }
    }
    
    return request
}
Copy the code

Cancel all Moya requests

// MARK: - Cancel all requests funccancelAllRequest() {/ / MyAPIProvider. Manager. Session. InvalidateAndCancel () / / cancel all requests MyAPIProvider.manager.session.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasksin
        dataTasks.forEach { $0.cancel() }
        uploadTasks.forEach { $0.cancel() }
        downloadTasks.forEach { $0.cancel() }
    }
    
    //let sessionManager = Alamofire.SessionManager.default
    //sessionManager.session.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in
    //    dataTasks.forEach { $0.cancel() }
    //    uploadTasks.forEach { $0.cancel() }
    //    downloadTasks.forEach { $0.cancel() }
    //}

}
Copy the code

Over, to be continued

My Jane book also published Lewis Jane book has written wrong places, please correct.