【问题标题】:Swift Combine: finished with error [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled"Swift 组合:完成错误 [-999] 错误域 = NSURLErrorDomain 代码 = -999 “已取消”
【发布时间】:2021-10-24 20:32:45
【问题描述】:

我正在尝试通过 Restcountries API 获取数据,但出现了问题。当我尝试获取数据时,错误立即出现:

2021-08-24 17:36:44.851463+0200 国家[1498:19786] 任务 . 以错误结束 [-999] 错误域 = NSURLErrorDomain 代码 = -999 “取消” UserInfo={NSErrorFailingURLStringKey=https://restcountries.eu/rest/v2/all, NSLocalizedDescription=cancelled, NSErrorFailingURLKey=https://restcountries.eu/rest/v2/all}

它每次都显示。知道如何解决吗?

API服务:

final class APIService: APIServiceProtocol {


func fetchAllCountries(url: URL) -> AnyPublisher<[Country], APIError> {
    
    let request = URLRequest(url: url)
    
    return URLSession.DataTaskPublisher.init(request: request, session: .shared)
        .tryMap { data, response in
            guard let httpResponse = response as? HTTPURLResponse, 200..<300 ~= httpResponse.statusCode else {
                throw APIError.unknown
            }
            
            return data
    }
    .decode(type: [Country].self, decoder: JSONDecoder())
    .mapError { error in
        if let error = error as? APIError {
            return error
        } else {
            return APIError.apiError(reason: error.localizedDescription)
        }
    }
    .eraseToAnyPublisher()
}

}

列表视图模型:

import SwiftUI
import Combine

class ListViewModel: ObservableObject {
    
    private let apiService: APIServiceProtocol
    @Published var countries = [Country]()
    
    init(apiService: APIServiceProtocol = APIService()) {
        self.apiService = apiService
    }
    
    func fetchCountries() {
        
        guard let url = URL(string: "https://restcountries.eu/rest/v2/all") else { return }
        
        let publisher = apiService.fetchAllCountries(url: url)
            .receive(on: DispatchQueue.main)
            .sink(receiveCompletion: { completion in
                switch completion {
                case .finished:
                    break
                case .failure(let error):
                    print(error.localizedDescription)
                }
            }, receiveValue: { data in
                self.countries = data
                print(data)
        })
        publisher.cancel()
    }
    
}

【问题讨论】:

    标签: ios swift nsurl combine


    【解决方案1】:

    您必须将发布者分配给 strong 引用,否则它会立即自行取消。

    创建属性

    var cancellable : AnyCancellable?
    

    分配

    cancellable = apiService.fetchAllCountries(url: url) ...
    

    并取消finished范围内的发布者

    case .finished:
        cancellable?.cancel()
    

    但是,如果发布者是 one-shot 发布者,cancel 行是多余的。当发布者发出finished 时,管道终止。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-19
      • 2020-02-22
      • 1970-01-01
      • 2017-03-14
      • 2015-11-14
      • 2019-04-22
      • 1970-01-01
      • 2013-12-30
      相关资源
      最近更新 更多