swift网络请求封装(Moya)

最近打算自己写个项目练练手,在弄到网络请求这块,发现之前用的都不是特别好用,于是想着还是自己手动封装一下,于是如下:
所用的第三方库:

pod 'Moya'
pod 'Reachability'
pod 'MBProgressHUD'
pod 'HandyJSON'
pod 'Result'

swift网络请求封装(Moya)_第1张图片
对于moya用法大家参照官方文档我就直接cv了,如下:
新建类NetManager

//
//  NetManager.swift
//  
//
//  Created by  on 2022/4/12.
//

import Moya
import MBProgressHUD
import HandyJSON
import Result
import CWLog

//MARK: loading插件,组合API请求,可在请求中自动补充loading
let LoadingPlugin = NetworkActivityPlugin { (type, target) in
//    guard let vc = topVC else {return}
    switch type {
    case .began: break
    case .ended: break
    }
    
}

//MARK: 超时中间件
let timeoutClosure = {(endpoint: Endpoint, closure: MoyaProvider.RequestResultClosure) -> Void in
    
    if var urlRequest = try? endpoint.urlRequest() {
        urlRequest.timeoutInterval = 20
        closure(.success(urlRequest))
    } else {
        closure(.failure(MoyaError.requestMapping(endpoint.url)))
    }
}

//MARK: 无loading请求
let ApiProvider = MoyaProvider(requestClosure: timeoutClosure)
//MARK: 有loading请求
let ApiLoadingProvider = MoyaProvider(requestClosure: timeoutClosure, plugins: [LoadingPlugin])


enum NetManager {
    case Recommend(device_id: String, model: String,sTime: String,systemVersion: String, target: String, time: String, version: String)
    case searchHot//搜索热门
    
}

extension NetManager: TargetType {
    var path: String {
        switch self {
        case .Recommend:
            return "/Recommend/head"
        case .searchHot:
            return "search/hotkeywordsnew"
        }
    }
    
    var method: Moya.Method {
        return .get
    }
    
    var task: Task {
        var paramters: [String : Any] = [:]
        switch self {
        case .Recommend(let device_id, let model, let sTime, let systemVersion, let target, let time, let version):
            paramters["device_id"] = device_id
            paramters["model"] = model
            paramters["sTime"] = sTime
            paramters["systemVersion"] = systemVersion
            paramters["target"] = target
            paramters["time"] = time
            paramters["version"] = version
        default:break
        }
        return .requestParameters(parameters: paramters, encoding: URLEncoding.default)
    }
    
    var sampleData: Data { return "".data(using: String.Encoding.utf8)! }
    
    var headers: [String : String]? {
        return nil
    }
    
    var baseURL: URL {
        return URL(string: "https://app.u17.com/v3/appV3_3/ios/phone")!
    }
    
}

//MARK: 请求结果解析模型
extension Response {
    func mapModel(_ type: T.Type)throws -> T {
        let jsonString = String(data: data, encoding: .utf8)
        CWLog(jsonString)
        guard let model = JSONDeserializer.deserializeFrom(json: jsonString) else {
            throw MoyaError.jsonMapping(self)
        }
        return model
    }
}

//MARK: 统一请求封装
extension MoyaProvider {
    @discardableResult
    open func request(_ target: Target,
                                    model: T.Type,
                                    completion:((_ returnData: T?) -> Void)?
    ) -> Cancellable? {
        return request(target) { result in
            debugPrint(result.value)
            guard let completion = completion else {
                return
            }

            guard let returnData = try? result.value?.mapModel(ResponseData.self) else {
                completion(nil)
                return
            }
            completion(returnData.data?.returnData)
        }
    }
}


以上就是其实就是moya简单的使用只不过对于请求的结果利用了HandyJSON进行了转化返回的结果直接就是model类型了
其中要注意一下:
所写的model类要按照HandyJSON规则去写如下:

struct QTitleModel : HandyJSON {
    var title: String? = nil
    var type: String? = nil
    var tag: String? = nil
    var search_hot: String? = nil
    var id: String? = nil
    var banner_id: String? = nil
    var is_recommend: String? = nil
    var url: String? = nil
}
extension Array: HandyJSON{}
struct ReturnData: HandyJSON {
    var message:String?
    var returnData: T?
    var stateCode: Int = 0
}

struct ResponseData: HandyJSON {
    var code : Int = 0
    var message: String?
    var data: ReturnData?
}

其中的RseponseData在NetManager类中已使用,如果模型中有复杂的模型转换,只需将包含的key对用的value值对应为你所写的类即可
例如:数据中包含QTitleModel列表,那可这样写:

struct QTitleList: HandyJSON {
    var  returnData: [QTitleModel]?
}

使用:

/** 网络请求 */
extension HomeViewController {
    func loadData() {
        let device_id = "69EACCA0-47C8-40EE-835F-7C02D8105F93"
        let model = "iPhone%207%20Plus"
        let sTime = "1624922081"
        let systemVersion = "13.3.1"
        let target = "U17_3.0"
        let time = "1649726510"
        let version = "5.8.0"
        
        ApiLoadingProvider.request(NetManager.Recommend(device_id: device_id, model: model, sTime: sTime, systemVersion: systemVersion, target: target, time: time, version: version), model: Array.self) { returnData in
            self.titles = returnData!
            
        }
    }
}

简单粗暴!!!

你可能感兴趣的:(swift,iOS,Xcode,swift,模型转化,复杂的模型转化,iOS,iOS网络请求封装)