Moya
是一个流行的 Swift 网络抽象层,被用于简化 iOS 应用程序中的网络请求。使用 Moya
,可以定义网络请求的方式,增加类型安全性,因为所有的网络请求都是经过 Swift 类型系统检查的,并且 Moya
提供了一种很好的方式来将网络请求代码组织得更加清晰和可维护。
Moya
的核心是一个 TargetType
协议,它定义了一个 API 端点的所有必要信息,包括路径、方法、任务、HTTP 任务和可能的测试数据。开发者需要为所消费的每一个 API 端点创建一个符合 TargetType
协议的枚举 case。
官网:https://github.com/Moya/Moya/blob/master/Readme_CN.md
1. 首先在项目中添加Moya 依赖
xcode swiftui项目添加依赖-CSDN博客
2.定义网络通用模型
比如你的接口返回数据结构如下:
{code:200,message:"成功",data:{}
}
定义一个BaseDetailResponse结构体为网络通用模型
import HandyJSON// 通用网络请求模型
struct BaseDetailResponse<T: HandyJSON>: HandyJSON {var code: Int?var message: String?var data: T?
}
3. 定义一个 TargetType
协议的枚举
import Moyaenum RequestApi {//获取会议信息case getMeetingroom(meetingNum:Int)
}// MARK: - 实现TargetType协议
extension RequestApi:TargetType{var sampleData: Data {switch self {case .getMeetingroom:return "{\"token\": \"sample token\"}".data(using: .utf8)!// 其他 API 请求的测试数据...case .getCaptions:return "{\"token\": \"sample token\"}".data(using: .utf8)!}}var baseURL: URL {let url = "域名"return URL(string: url)!}// 返回每个请求的路径var path: String {switch self{case .getMeetingroom:return "xx/xx"default:fatalError("Request path is null")}}var method: Moya.Method {switch self{case .getMeetingroom:return .postdefault:return.get}}var task: Moya.Task {switch self{case .getMeetingroom(let meetingNum):// 用于编码成x-www-form-urlencoded的参数let params: [String: Any] = ["meetingNum": meetingNum]return .requestParameters(parameters: params, encoding: URLEncoding.default)default://不传递任何参数return .requestPlain}}/// 请求头var headers: [String : String]? {var headers:Dictionary<String,String> = [:]//内容的类型switch self{case .getMeetingroom:headers["Content-Type"]="application/x-www-form-urlencoded"breakdefault:break}return headers}
}
4. 定义接口返回数据模型
若getMeetingroom返回数据结构为
{meetingNum:4234234234,meetingName:"会议"
}
定义会议信息结构体
struct MeetingInfo: HandyJSON {var meetingNum:Intvar meetingName:Stringinit() {self.meetingNum = 0self.meetingName = ""}
}
5. 初始化网络请求,发送请求
使用 MoyaProvider
来初始化网络请求,发送请求,并处理响应或者错误。
//
// DoRequest.swift
//import Foundation
import Moya
import RxSwift
import HandyJSONclass DoRequest{static let shared = DoRequest()private var provider:MoyaProvider<RequestApi>!// MARK:func getMeetingroom(data:Int, completion: @escaping (BaseDetailResponse<MeetingInfo>?, Error?) -> ()) {provider.request(.getMeetingroom(meetingNum: data)){ result inswitch result {case let .success(response):if let jsonResponse = BaseDetailResponse<MeetingInfo>.deserialize(from: String(data: response.data, encoding: .utf8)) {completion(jsonResponse, nil)} else {print("Decoding Error")completion(nil, DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Decoding error")))}case let .failure(error):print(error.errorDescription ?? "error")completion(nil, error)}}}/// 私有构造方法 主要为了打印后台请求到的数据 便于查看private init() {//网络请求加载对话框let networkActivityPlugin = NetworkActivityPlugin { change, target in//changeType类型是NetworkActivityChangeType//通过它能监听到开始请求和结束请求 //targetType类型是TargetType//就是我们这里的service //通过它能判断是那个请求if change == .began {//开始请求let targetType = target as! RequestApiswitch targetType {case .getMeetingroom:DispatchQueue.main.async {//切换到主线程 才可以操作view}default:break}} else {//结束请求DispatchQueue.main.async {}}}plugins.append(networkActivityPlugin)provider = MoyaProvider<RequestApi>(plugins: plugins)}
}
5. 使用示例
let intValue = Int("4234234234")!let meetingInfo = MeetingInfo()DoRequest.shared.getMeetingroom(data: intValue) { (response, error) inif let response = response {if let code = response.code{if(code == 200){// 处理你的响应if let data = response.data {// Use meetingRoomInfo heremeetingInfo = data}}else{self.alertMessage = response.message!self.showAlert = true}}} else if let error = error {//登录失败self.showAlert = trueself.alertMessage = error.localizedDescriptionreturn}}