最开始自己也是使用Alamofire进行网络请求,后面听说有Moya这种请求方法。一下就喜欢上了。话不多说,下面直接上代码。
import Moya
import Result
enum API {
case login(parameters:[String: Any]) // 登录
case getAllProjUser // 获取用户参与的所有项目
}
然后实现TargetType这个协议。Xcode会提示需要添加的代码,点击提示自动补全代码。这里在method会报一个错误。需要改成Moya.Method就OK。
extension API:TargetType{
var baseURL: URL {
return URL(string: "https://www.baidu.com?search=")!
}
var path: String {
switch self {
case .login:
return "Login"
case .getAllProjUser:
return "GetAllProj"
}
}
var getPartmeters: [String: Any]{
switch self {
case let .login(dict):
return dict
case .getAllProjUser:
return [:]
}
}
var task: Task {
return .requestParameters(parameters: getPartmeters, encoding: JSONEncoding.default)
}
var method: Moya.Method {
return .post
}
var sampleData: Data {
return Data()
}
var headers: [String : String]? {
return nil
}
}
到此,API设计就完成了。下一步进行网络请求方法的代码。
在这里,我们设置了myEndpointClosure。主要是设置超时时间和解决URL带有?时,无法正确的链接地址的bug。在没知道这个之前,我还是通过修改源码来解决这个问题。
import Moya
/// 超时时长
private var requestTimeOut:Double = 30
///endpointClosure
private let myEndpointClosure = { (target: API) -> Endpoint in
///主要是为了解决URL带有?无法请求正确的链接地址的bug
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
)
switch target {
case .login:
requestTimeOut = 5//按照项目需求针对单个API设置不同的超时时长
return endpoint
default:
requestTimeOut = 30//设置默认的超时时长
return endpoint
}
}
struct Network {
static let provider = MoyaProvider<API>(endpointClosure: myEndpointClosure)
static func request(_ target: API, successCallback: @escaping ([String:Any]) -> Void,
failure failureCallback: @escaping (String) -> Void){
provider.request(target) { (result) in
switch result{
case let .success(response):
if let json = try? response.mapJSON() as! [String:Any]{
successCallback(json)
}
else{
print("服务器连接成功,数据获取失败")
}
case let .failure(error):
failureCallback(error.errorDescription!)
}
}
}
// MARK: - 取消所有网络请求
static func cancelAllRequest(){
provider.manager.session.getAllTasks { (tasks) in
tasks.forEach{
print("取消网络请求一次")
$0.cancel()
}
}
}
}
下一步是使用方法,上代码。
let parameters = ["account":account,"password":password]
Network.request(.login(parameters: parameters), successCallback: { (json) in
print(json)
}) { (msg) in
print(msg)
}
}