在前一篇文章里我们通过对 URLSession 扩展并配合 Result和Decodable包装一个访问远程API的组件,本文将利用相同的原理,使用我们学习过的Combine来包装一个 抓取 API的组件。
本组件所有代码的实现原理和上一篇文章类似。重复的内容,本文将不再赘述。首先需要我们掌握Combine的相关知识。
import Foundation
import Combine
class NetworkService{
static let shared = NetworkService()
private init() { }
private var cancellables = Set<AnyCancellable>()
func getData(_ request: URLRequest, decode decodable: T.Type) -> Future<T, Error> {
return Future<T, Error> { [weak self] promise in // promise 返回 (Result<[T], Error>)
guard let self = self else {
return promise(.failure(APIError.badURL))
}
// print("当前请求为:(request.url?.description ?? "无效URL")")
URLSession.shared.dataTaskPublisher(for: request)
.tryMap { (data, response) -> Data in
guard let httpResponse = response as? HTTPURLResponse, 200...299 ~= httpResponse.statusCode else { // “~=” 查看statusCode是否在200到299的范围内
throw APIError.noResponse
}
return data
}
.decode(type: decodable.self, decoder: JSONDecoder())
.receive(on: RunLoop.main)
.sink(receiveCompletion: { (completion) in
if case let .failure(error) = completion {
switch error {
case let decodingError as DecodingError:
promise(.failure(decodingError))
case let apiError as APIError:
promise(.failure(apiError))
default:
promise(.failure(APIError.unknown))
}
}
}, receiveValue: {
promise(.success($0))
})
.store(in: &self.cancellables)
}
}
}
//使用Combine
private var cancellables = Set<AnyCancellable>()
func fetchData(){
fetchStatus = .fetching
let request = APIService.shared.getURL(endpoint: .recommend, params: nil)
NetworkService.shared.getData(request, decode: JSONModel<RecommendedModel>.self)
.sink {
switch $0 {
case .finished:
print("ComBine完成发布")
case .failure(let error):
self.fetchStatus = .failed
print("ComBine发布出错了:",error)
}
} receiveValue: { [weak self] details in
self?.datas = details.data//映射数据
self?.fetchStatus = .idle
}
.store(in: &cancellables)//将此类型擦除可取消实例存储在指定集中。
}
除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/189
《【APP开发】使用Combine包装一个访问远程API的组件》的网友评论(0)