MHNetwork
基于协议的网络层,旨在避免使用臃肿的单例NetworkManager
哲学
MHNetwork的主要哲学是单一职责。如果代码中的每个类都只有一个任务且仅有一个任务去做,这将大大简化问题的定位。因此,最初...
安装
$ pod install MHNetwork
或者在您的podfile中
pod 'MHNetwork'
您还可以使用Swift Package Manager
用法
假设您有电影API,需要发起请求来获取电影列表...
您需要为您要实现的功能创建两个文件:MoviesRequests.swift
和MoviesTasks.swift
在请求文件中,代码应如下所示
import Foundation
import MHNetwork
enum MoviesRequests: Request {
case getMoviesList
var path: String {
return "movies/list/"
}
var method: HTTPMethod {
switch self {
case .getRandomQuote:
return .get
}
}
var parameters: RequestParams {
return .url(["year" : "2018"])
// can use .body(["year": "20018"]) if the api require body parameters
}
var headers: [String : Any]? {
return ["Authorization": "xyz"]
}
}
然后加入任务
class QuoteTask <T: Codable>: Operations {
var request: Request {
return MoviesRequests.getMoviesList
}
func exeute(in dispatcher: Dispatcher, completed: @escaping (Result<T, NetworkError>) -> Void) {
do {
try dispatcher.execute(request: self.request, completion: { (result) in
switch result {
case .success(let response):
switch response {
case .data(let data):
do {
let decoder = JSONDecoder()
// decoder.keyDecodingStrategy = .convertFromSnakeCase
// uncomment this in case you have some json properties in Snake Case and you just want to decode it to camel Case... workes only for swift 4.1 or higher
let object = try decoder.decode(T.self, from: data)
completed(.success(object))
} catch let error {
print("error Parsing with Error: \(error.localizedDescription)")
}
break
case .error(let error):
completed(.failure(error))
break
}
case .failure(let error):
completed(.failure(error))
}
})
} catch {
completed(.failure(.error(code: nil, error: error, data: nil)))
}
}
}
这样就完成了对请求的基本设置,现在您可以从代码中调用它
func getMoviesList(onComplete: @escaping (Movie) -> Void, onError: @escaping (Error) -> Void) {
let environment = Environment(host: "https://imdb.com/api")
let networkDispatcher = NetworkDispatcher(environment: environment, session: URLSession(configuration: .default))
let moviesTask = MoviesTasks<Movie>() // Movie Model should be codable
moviesTask.exeute(in: networkDispatcher) { (result) in
switch result {
case .success(let users):
onCompletion(movies)
case .failure(let error):
onError(error)
}
})
}
就是这样……最后提醒一点……创建MoviesTask实例时,注意到了注释 Movie模型应该是Codable的
,嗯,这不是必须的,但这是我的首选方式。你可以根据任务本身进行适配,如果你想让它更加灵活一些,也可以。但你需要以另一种方式处理返回的数据。
待办事项://
- 需要支持JSON返回类型,而不依赖于任何第三方库
- 需要修复和清理示例测试用例和代码
贡献://
从Develop分支创建分支/编辑/Pull request... 你知道该怎么做 ;)