Moya是通过面向协议编程(POP)的思想来设计的一个网络抽象库,是对Alamofire的封装。
我对Moya简单的二次封装例子如下:
一、网络模块主要包括三部分
1.NetWorkConfig部分是做全局的配置,代码如下
//
// NetWorkConfig.swift
// XCX_test
//
// Created by 王成杰 on 2020/3/25.
// Copyright © 2020 wangcj. All rights reserved.
//
import Foundation
//baseUrl
let BaseUrl = "https://baidu.com"
//是否打印请求信息
let NetWorkLog = true
// 数据返回状态key
let NetWorkResCodeKey = "code"
// 数据成功的状态码code
let NetWorkSuccessCode = 0
// 数据消息提示key
let NetWorkResMessageKey = "msg"
2.NetWorkBaseApi部分是遵守TargetType协议的类,来实现网络请求request的组建,代码如下
// NetWorkBaseApi.swift
// XCX_test
//
// Created by 王成杰 on 2020/3/25.
// Copyright © 2020 wangcj. All rights reserved.
//
import Foundation
import Moya
enum RequestType {
case GET
case POST
case DELETE
}
private var tempPath: String?
private var tempParam: [String:Any]?
private var requestType: RequestType?
class Target {
typealias complateClosure = (Dictionary<String, Any>?, Error?) -> (Void)
class func callRequestWithControl(control: NSObject, path: String, params: [String: Any] , type: RequestType, onComplete: @escaping complateClosure ) {
tempPath = path
tempParam = params
requestType = type
NetWorkManager.shared.request(target:Target()) { (data, error) -> (Void) in
onComplete(data,error)
}
}
}
extension Target: TargetType {
var baseURL: URL {
return URL.init(string: BaseUrl)!
}
var path: String {
return tempPath ?? ""
}
var method: Moya.Method {
switch requestType {
case .GET:
return .get
case .POST:
return .post
case .DELETE:
return .delete
case .none:
return .get
}
}
var sampleData: Data {
return "".data(using: String.Encoding.utf8)!
}
var task: Task {
return .requestParameters(parameters: tempParam ?? [:], encoding: URLEncoding.default)
}
var headers: [String : String]? {
//公共参数
return ["api_version" : "1.0.0",]
}
}
3.NetWorkManager部分是负责发起请求以及对返回结果的处理,代码如下
// NetWorkManager.swift
// XCX_test
//
// Created by 王成杰 on 2020/3/25.
// Copyright © 2020 wangcj. All rights reserved.
//
import Foundation
import Moya
import Alamofire
//超时时间
private var requestTimeOut: Double = 15
struct NetWorkManager {
//MARK: - Closures
typealias complateClosure = (Dictionary<String, Any>?, Error?) -> (Void)
//MARK: - getters setters
private let endpointClosure = { (target: Target) -> Endpoint in
let url = target.baseURL.absoluteString + target.path
var endpoint = Endpoint(
url: url,
sampleResponseClosure: { .networkResponse(200, target.sampleData) },
method: target.method,
task: target.task,
httpHeaderFields: target.headers
)
return endpoint
}
private let requestClosure = { (endpoint: Endpoint, closure: MoyaProvider.RequestResultClosure) in
do {
var request = try endpoint.urlRequest()
request.timeoutInterval = requestTimeOut
if NetWorkLog {
if let requestData = request.httpBody {
print("\(request.url!)"+"\n"+"\(request.httpMethod ?? "")"+"发送参数"+"\(String(data: request.httpBody!, encoding: String.Encoding.utf8) ?? "")")
}else{
print("\(request.url!)"+"\(String(describing: request.httpMethod))")
}
}
closure(.success(request))
} catch {
closure(.failure(MoyaError.underlying(error, nil)))
}
}
private let networkPlugin = NetworkActivityPlugin.init { (changeType, targetType) in
switch(changeType){
case .began:
print("开始请求")
case .ended:
print("请求结束")
}
}
//MARK:- life
static let shared = NetWorkManager()
private init() {}
//MARK: - public methods
//取消所有请求
func cancelAllRequest() {
Alamofire.SessionManager.default.session.getTasksWithCompletionHandler {
(sessionDataTask, uploadData, downloadData) in
sessionDataTask.forEach { $0.cancel() }
uploadData.forEach { $0.cancel() }
downloadData.forEach { $0.cancel() }
}
}
//取消指定URL的请求
func cancelRequest(url: String){
Alamofire.SessionManager.default.session.getTasksWithCompletionHandler {
(sessionDataTask, uploadData, downloadData) in
sessionDataTask.forEach {
if ($0.originalRequest?.url?.absoluteString == url) {
$0.cancel()
}
}
}
}
//网络状态判断
func currentNetReachability() {
let manager = NetworkReachabilityManager()
manager?.listener = { status in
var statusStr: String?
switch status {
case .unknown:
statusStr = "未识别的网络"
break
case .notReachable:
statusStr = "不可用的网络(未连接)"
//toast
return
case .reachable:
if (manager?.isReachableOnWWAN)! {
statusStr = "2G,3G,4G...的网络"
} else if (manager?.isReachableOnEthernetOrWiFi)! {
statusStr = "wifi的网络"
}
break
}
debugPrint(statusStr as Any)
}
manager?.startListening()
}
//MARK: - request
func request(target: Target, completion: @escaping complateClosure) {
//判断网络状态
currentNetReachability()
let provider = MoyaProvider(endpointClosure: endpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)
provider.request(target) { (result) in
switch result {
case let .success(response):
do {
//转JSON
let responseDict = try JSONSerialization.jsonObject(with: response.data)
guard let dic = responseDict as? Dictionary<String, Any> else {
debugPrint("不是json数据")
return
}
if let code = dic[NetWorkResCodeKey] as? Int, code == NetWorkSuccessCode {
completion(dic,nil )
}else {
let message = dic[NetWorkResMessageKey] as? String ?? "数据错误"
debugPrint(message)
//aleart
}
} catch {
debugPrint("数据转字典失败")
}
case let .failure(error):
if let errorDescription = error.errorDescription {
completion(nil, error)
debugPrint("网络请求失败:\(errorDescription)")
}else {
//网络连接失败
debugPrint("网络连接失败")
}
}
}
}
}
二、网络请求的使用如下
创建继承自Target的类MyTestRequest,代码如下
// MyTestRequest.swift
// XCX_test
//
// Created by 王成杰 on 2020/3/25.
// Copyright © 2020 wangcj. All rights reserved.
//
import Foundation
class MyDataEngine: Target {
class func changePhoneNumberInfo(withControl: AnyObject, orderNum: String, mobileNum: String, complate: @escaping complateClosure ){
callRequestWithControl(control: withControl as! NSObject, path: "/order/detail", params: ["order_number":orderNum ,"mobile":mobileNum], type: .GET, onComplete: complate)
}
}
三、具体业务中的调用如下
private func getMyData(){
MyDataEngine.changePhoneNumberInfo(withControl: self, orderNum: "111", mobileNum: "18543434354") { (data, error) -> (Void) in
print(data as Any)
}
}
学习Moya
为了能兼容老项目用Moya简单封装的,也是为了学习Moya,抛砖引玉还请指正
学习