简体   繁体   English

SwiftUI 中的“任务已完成,但出现错误 [-999]”

[英]"Task finished with error [-999]" in SwiftUI

I am trying to make an HTTP GET request using Combine to the https://myLink.com URL (this is a fake URL, the one that I use is a real API link and it works, but I can't post it), but when I call the function I get the following error:我正在尝试使用组合到https://myLink.com URL 发出 HTTP GET 请求(这是一个假 URL,我使用的是一个真正的 API 链接并且它有效,但我无法发布它) ,但是当我调用该函数时,出现以下错误:

Task <18F5A03A-96DF-4309-B263-B6B0CB275779>.<1> finished with error [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey= https://myLink.com , NSLocalizedDescription=cancelled, NSErrorFailingURLKey= https://myLink.com }任务 <18F5A03A-96DF-4309-B263-B6B0CB275779>.<1> 已完成,但出现错误 [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey= https://myLink.com , NSLocalizedDescription=cancelled , NSErrorFailingURLKey= https://myLink.com }

Here is my code:这是我的代码:

import SwiftUI
import Foundation
import Combine

struct ContentView: View {
   var body: some View {
      Button(action: {
         loadPatients()
      })
      {
         Text("Load Patients")
      }
   }
}

//MARK: - Your object to retrieve from JSON
struct Doctor: Codable, Identifiable {
  let id = UUID()
  let patients: [Patients]
}

struct Patients: Codable {
  let id: String
  let name: String
  let phone: String
}

class Network {

  // Handle your request errors
  enum Error: LocalizedError {
    case invalidResponse
    case addressUnreachable(URL)

    var errorDescription: String? {
      switch self {
      case .invalidResponse:
        return "The server responded with garbage."
      case .addressUnreachable(let url):
        return "\(url.absoluteString) is unreachable."
      }
    }
  }

  // Add your url
  let urlRequest = URL(string: "https://coronavirus-med.herokuapp.com/api/v1/doctor/getPatients/bogdand")!

  // Networking on concurrent queue
  let networkQueue = DispatchQueue(label: "Networking",
                                   qos: .default,
                                   attributes: .concurrent)

  // Combine network call (This replace your previous code)
  func downloadPatients() -> AnyPublisher<Doctor, Error> {
    URLSession.shared
      .dataTaskPublisher(for: urlRequest)
      .receive(on: networkQueue)
      .map(\.data)
      .decode(type: Doctor.self, decoder: JSONDecoder())
      .mapError { (error) -> Network.Error in
        switch error {
        case is URLError:
          return Error.addressUnreachable(self.urlRequest)
        default:
          return Error.invalidResponse
        }
    }
    .eraseToAnyPublisher()
  }
}

let networkRequest = Network()

//MARK: - Call this function where you want to make your call
func loadPatients() {
  _ = networkRequest.downloadPatients()
    .sink(
      receiveCompletion: {
        print("Received Completion: \($0)") },
      receiveValue: { doctor in
        // doctor is your response and [0].name is your first patient name
        print(doctor.patients[0].name) }
  )
}

I found another question on StackOverflow addressing this error, but the answer just says what the error means, but not how to solve it.我在 StackOverflow 上发现了另一个问题来解决这个错误,但答案只是说明了错误的含义,而不是如何解决它。 They said that it means that a request is made before another one is finished, but I don't make any requests before this one, I even tried to run this in a new empty project but it still gives me the same error.他们说这意味着在另一个请求完成之前提出了一个请求,但我在这个请求之前没有提出任何请求,我什至尝试在一个新的空项目中运行它,但它仍然给我同样的错误。

I was on iOS 13.2 and Xcode 11.2 and I updated to iOS 13.4 and Xcode 11.4, still the same error.我在 iOS 13.2 和 Xcode 11.2 上更新到 iOS 13.4 和 Xcode 11.4,仍然是同样的错误。

This is the JSON response:这是 JSON 响应:

{
    "code": 200,
    "status": "success",
    "patients": [
        {
            "_id": "5e77c7bbc7cbd30024f3eadb",
            "name": "Bogdan Patient",
            "username": "bogdanp",
            "phone": "0732958473"
        },
        {
            "_id": "5e77c982a2736a0024e895fa",
            "name": "Robert Patient",
            "username": "robertp",
            "phone": "0739284756"
        }
    ]
}

To get the result from network call you need to change your content view in this way:要从网络调用中获得结果,您需要以这种方式更改内容视图:

struct ContentView: View {

    let networkRequest = Network()
    @State var cancelable: AnyCancellable? = nil

    var body: some View {
        Button(action: {
            self.loadPatients()
        })
        {
            Text("Load Patients")
        }
    }

    //MARK: - Call this function where you want to make your call
    func loadPatients() {
       cancelable = networkRequest.downloadPatients()
            .sink(
                receiveCompletion: {
                    print("Received Completion: \($0)") },
                receiveValue: { doctor in
                    // doctor is your response and [0].name is your first patient name
                    print(doctor.patients[0].name) }
        )
    }

}

you should store the network call in AnyCancellable .您应该将网络调用存储在AnyCancellable When using it inside a view, you need to use a @State variable, to make sure it survives after the view body was generated.在视图中使用它时,您需要使用 @State 变量,以确保它在生成视图主体后仍然存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM