Implementation Method of iOS Using Moya Network Request

Time:2019-10-14

As I wrote this article a while ago, the latest Moya has updated the latest version, so I have updated the following usage. I have used it, and I intentionally send you the latest demo for your reference. Moya 11.0.2 Demo

Moya introduction

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

Moya has several good features:

  • Check the correct API endpoint access at compile time.
  • Make it clearer for you to define different endpoint enumeration values for the corresponding purposes.
  • Improve the testing status to make unit testing easier.

Swift, we useAlamofireTo build a network library, Moya encapsulates another layer on the basis of Alamofire, as illustrated in the following flowchartMoyaSimple workflow chart of:

Moya’s official download address is my powerful Moya, and there are specific ways to use it in demo.

This article mainly introducesMoyaUsage

  • Set request header settings
  • Set timeout time
  • Custom plug-in
  • Self-signed certificate

Note: The following appearsNetAPIManagerGitHub** is the same type of file as demo ** on official website. It is this enum that implements a protocol called TargetType. Click in and you can see that TargetType defines what we need to send a network request, what baseURL, parameter, method and other computational attributes. What we need to do is to implement these things. Of course, with default values, we can not implement them. But setting header information and timeout time will change the default settings of these systems.

In order to see more clearly, paste it onNetAPIManagerContent of the document

//
// NetAPIManager.swift
// NN110
//
// Created by Chen Yihai on 2017/5/12.
// Copyright 2017 Chen Yihai. All rights reserved.
//

import Foundation
import Moya


enum NetAPIManager {
 case Show
 case upload(bodyData: Data)
 case download
 case request(isTouch: Bool, body: Dictionary<String, Any>? ,isShow: Bool)
}


extension NetAPIManager: TargetType {
 Var base URL: URL {// server address
  
  switch self {
  case .request( _, _, _):
   return URL(string: "https://www.pmphmall.com")!
  default:
   return URL(string: "https://httpbin.org")!
  }
  
  
 }
 
 Var path: String {// the path of a particular method
  switch self {
  case .Show:
   return ""
  case .upload(_):
   return ""
  case .request(_, _, _):
   return "/app/json.do"
  case .download:
   return ""
  }
 }
 
 Var method: Moya. Method {// Request method get or post
  switch self {
  case .Show:
   return .get
  case .request(_, _, _):
   return .post
  default:
   return .post
  }
 }
 
 Var parameters: [String: Any]? {// Request get post to server parameters
  switch self {
  case .Show:
   return nil
  case .request(_, _, _):
   return ["msg":"H4sIAAAAAAAAA11SSZJFIQi7EqPAEgTvf6TP62W7sMoSQhKSWDrs6ZUKVWogLwYV7RjHFBZJlNlzloN6LVqID4a+puxqRdUKVNLwE1TRcZIC/fjF2rPotuXmb84r1gMXbiASZIZbhQdKEewJlz41znDkujCHuQU3dU7G4/PmVRnwArMLXukBv0J23XVahNO3VX35wlgce6TLUzzgPQJFuHngAczl6VhaNXpmRLxJBlMml6gdLWiXxTdO7I+iEyC7XuTirCQXOk4dotgArgkH/InxVjfNTnE/uY46++hyAiLFuFL4cv1Z8WH5DgB2GnvFXMh5gm53Tr13vqqrEYtcdXfkNsMwKB+9sAQ77grNJmquFWOhfXA/DELlMB0KKFtHOc/ronj1ml+Z7qas82L3VWiCVQ+HEitjTVzoFw8RisFN/jJxBY4awvq427McXqnyrfCsl7oeEU6wYgW9yJtj1lOkx0ELL5Fw4z071NaVzRA9ebxWXkFyothgbB445cpRmTC+//F73r1kOyQ3lTpec12XNDR00nnq5/YmJItW3+w1z27lSOLqgVctrxG4xdL9WVPdkH1tkiZ/pUKBGhADAAA="]
  default:
   return nil
  
  }
 }
 
 Var sampleData: Data {// Code Escape
  return "{}".data(using: String.Encoding.utf8)!
 }
 
 Var task: Task {// a request task event
  
  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: Format of ParameterEncoding {// Encoding
  switch self {
  case .request(_, _, _):
   return URLEncoding.default
  default:
   return URLEncoding.default
  }
  
 }
 // The following two parameters are written by me to control whether the operation is allowed when the network is loaded and whether the loading prompt is displayed. These two parameters are used when customizing the plug-in.
 Var touch: Bool {// is operational
  
  switch self {
  case .request(let isTouch, _, _):
   return isTouch
  default:
   return false
  }
  
 }
 
 Var show: Bool {// Whether to show a turn-around prompt
  
  switch self {
  case .request( _, _,let isShow):
   return isShow
  default:
   return false
  }
  
 }
 
 
}

How to Set Moya Request Header Information

The setting of header information is very important in the development process, such as token generated by server, unique user ID and so on. We can directly code, not to mention so many theoretical things, haha.

// MARK: - Set the request header information
let myEndpointClosure = { (target: NetAPIManager) -> Endpoint<NetAPIManager> in
 
 
 let url = target.baseURL.appendingPathComponent(target.path).absoluteString
 let endpoint = Endpoint<NetAPIManager>(
  url: url,
  sampleResponseClosure: { .networkResponse(200, target.sampleData) },
  method: target.method,
  parameters: target.parameters,
  parameterEncoding: target.parameterEncoding
 )

 // Set up your HTTP header information here
 return endpoint.adding(newHTTPHeaderFields: [
  "Content-Type" : "application/x-www-form-urlencoded",
  "ECP-COOKIE" : ""
  ])
 
}

How to Set Request Timeout

//Mark: - set request timeout
let requestClosure = { (endpoint: Endpoint<NetAPIManager>, done: @escaping MoyaProvider<NetAPIManager>.RequestResultClosure) in
 
 guard var request = endpoint.urlRequest else { return }
 
 Request. timeout Interval = 30 /// Sets the request timeout time
 done(.success(request))
}

Custom plug-in

Custom plug-ins mustPluginTypeTwo methods of protocol willSend and didReceive

//
// MyNetworkActivityPlugin.swift
// NN110
//
// Created by Chen Yihai on 2017/5/10.
// 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<Moya.Response, MoyaError>, target: TargetType) {
  myNetworkActivityClosure(.ended,target)
 }
}

Using a custom plug-in method

// MARK: - Customized network prompt request plug-in
let myNetworkPlugin = MyNetworkActivityPlugin { (state,target) in
 if state == .began {
  //  SwiftSpinner.show("Connecting...")
  
  let api = target as! NetAPIManager
  if api.show {
   Print ("I can write load hints here")
  }
  
  if !api.touch {
   Print ("I can write here to prohibit user action and wait for the request to end")
  }

  Print ("I started requesting (api. touch)")
  
  UIApplication.shared.isNetworkActivityIndicatorVisible = true
 } else {
  //  SwiftSpinner.show("request finish...")
  //  SwiftSpinner.hide()
  Print ("I end request")
  UIApplication.shared.isNetworkActivityIndicatorVisible = false
  
 }
}

Self-signed certificate

In 16 years of WWDC, Apple has indicated that from January 1, 2017, ** all newly submitted Apps must be mandatory to apply HTTPS protocol for network requests. ** By default, non-HTTPS network access is prohibited and NSAllows ArbitraryLoads settings can no longer be added to Info.plist simply and roughly to circumvent ATS (App Transport Security) restrictions (otherwise, they must be explained during application audits and are likely to be rejected). So companies that haven’t yet done the corresponding configuration need to put the upgrade to HTTPS in the process as soon as possible. This article will briefly describe HTTPS and the principle of configuring digital certificates, and illustrate the configuration examples and problems, hoping to help you. (BI Xin ~)

HTTPS: Simply put, HTTPS is HTTP protocol plus a layer of encryption processing of the SSL protocol, namely HTTP security version. Compared with HTTP, HTTPS can ensure that the content will not be viewed by the third party in the transmission process, discover the content tampered with by the third party in time, and prevent identity impersonation, so as to ensure the security of network data more effectively. HTTPS client-server interaction process: 1. When the client first requests, the server will return a digital certificate containing the public key to the client; 2. The client generates the symmetric encryption key and encrypts it with the obtained public key, and then returns it to the server; 3. The server decrypts the encrypted data received by using its own private key, obtains the symmetric encryption key and saves it; 4. Then both sides transmit symmetrically encrypted data.

Digital Certificate: When HTTPS client and server interact for the first time, the digital certificate returned by the server to the client is to let the client verify whether the digital certificate is the server and whether the certificate owner is the server, so as to ensure that the data is sent by the correct server and not tampered with by the third party. A digital certificate can ensure that the public key in a digital certificate is indeed the owner of the certificate (Subject), or that the certificate can be used to confirm the identity of the other party. Certificates are composed of public key, certificate subject and digital signature. Digital signature is the anti-counterfeiting label of certificate, which is currently the most widely used SHA-RSA encryption. Certificates are generally divided into two types:

  1. One is a certificate purchased from an authoritative certification authority. When the server uses this certificate, because Apple system has its trusted signature root certificate built in, the client does not need additional configuration. For certificate security, the fingerprint algorithm of certificate will be encrypted and published together with certificate to prevent others from forging digital certificate when certificate issuing agency publishes certificate. Certificate institutions use their own private keys to encrypt their fingerprint algorithms, and can decrypt the root certificate of the institutional signature embedded in the operating system to ensure the security of the certificate.
  2. The other is self-made certificate, i.e. self-signed certificate. The advantage is that you don’t have to pay for two, but you won’t be trusted to use this certificate, soWe need to configure the certificate as a trust certificate in our code.

Specific implementation of self-signed certificates: When we use self-signed certificates to implement HTTPS requests, because their signature root certificates are built-in in the system, unlike certificates issued by institutions, we need to build our own server’s signature root certificates in App to verify digital certificates. First, add the root certificate in. cer format generated by the server to the project. Note that when adding certificates, you must remember to check the targets you want to add.

 Here’s a place to watch out for.Apple’s ATS requires the server to support TLS version 1.2 or more; must use passwords that support forward confidentiality; certificates must be signed using SHA-256 or better signature hash algorithm; if the certificate is invalid, it will lead to connection failure. Since my signature hash algorithm is lower than its requirement when I generate the root certificate, I always report when I configure the request.NSURLErrorServerCertificateUntrusted=- 1202 error, I hope you can pay attention to this point.

So how to use self-signed certificates to implement HTTPS network requests in Moya? Look forward to sharing with me next time… You need to customize a Manager management.

The methods of comprehensive use are as follows.

Define a common Moya request service object

let MyAPIProvider = MoyaProvider<NetAPIManager>(endpointClosure: myEndpointClosure,requestClosure: requestClosure, plugins: [NetworkLoggerPlugin(verbose: true, responseDataFormatter: JSONResponseDataFormatter),myNetworkPlugin])

// MARK: - Create a Moya request
func 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
}

Cancel all Moya requests

// MARK: - Cancel all requests
func cancelAllRequest() {
// MyAPIProvider. manager. session. invalidate AndCancel ()// Cancel all requests cancelled
 MyAPIProvider.manager.session.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in
  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() }
 //}

}

Finished, to be continued with more advanced usage.

The above is the whole content of this article. I hope it will be helpful to everyone’s study, and I hope you will support developpaer more.