最近打算自己写个项目练练手,在弄到网络请求这块,发现之前用的都不是特别好用,于是想着还是自己手动封装一下,于是如下:
所用的第三方库:
pod 'Moya'
pod 'Reachability'
pod 'MBProgressHUD'
pod 'HandyJSON'
pod 'Result'
对于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!
}
}
}
简单粗暴!!!