75142913在线留言
【APP开发】使用Combine包装一个访问远程API的组件_IOS开发_网络人

【APP开发】使用Combine包装一个访问远程API的组件

Kwok 发表于:2022-01-04 11:04:30 点击:33 评论: 0

在前一篇文章里我们通过对  URLSession 扩展并配合 Result和Decodable包装一个访问远程API的组件,本文将利用相同的原理,使用我们学习过的Combine来包装一个 抓取 API组件

本组件所有代码的实现原理和上一篇文章类似。重复的内容,本文将不再赘述。首先需要我们掌握Combine的相关知识。

一、封装Combine的API抓取代码 

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
标签:CombineAPI组件Kwok最后编辑于:2022-01-04 19:04:57
0
感谢打赏!

《【APP开发】使用Combine包装一个访问远程API的组件》的网友评论(0)

本站推荐阅读

热门点击文章