«Задача завершена с ошибкой [-999]» в SwiftUI - PullRequest
2 голосов
/ 26 марта 2020

Я пытаюсь сделать HTTP-запрос GET, используя Объединение к URL-адресу https://myLink.com (это фальшивый URL-адрес, который я использую, является реальной ссылкой API, и она работает, но я могу не публиковать), но когда я вызываю функцию, я получаю следующую ошибку:

Задача <18F5A03A-96DF-4309-B263-B6B0CB275779>. <1> завершена с ошибкой [-999] Ошибка домена = NSURLErrorDomain Code = -999 "отменено" UserInfo = {NSErrorFailingURLStringKey = https://myLink.com, NSLocalizedDescription = отменено, NSErrorFailingURLKey = https://myLink.com}

Вот мой код:

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) }
  )
}

Я нашел другой вопрос о StackOverflow, касающийся этой ошибки, но в ответе просто говорится, что означает ошибка, а не как ее решить. Они сказали, что это означает, что запрос сделан до того, как другой будет завершен, но я не делаю никаких запросов до этого, я даже пытался запустить его в новом пустом проекте, но он все еще дает мне ту же ошибку.

Я был на iOS 13.2 и Xcode 11.2, и я обновился до iOS 13.4 и Xcode 11.4, все та же ошибка.

Это ответ JSON:

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

1 Ответ

1 голос
/ 26 марта 2020

Чтобы получить результат от сетевого вызова, вам нужно изменить вид контента следующим образом:

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) }
        )
    }

}

Вы должны сохранить сетевой вызов в AnyCancellable. При использовании его внутри представления вам необходимо использовать переменную @State, чтобы убедиться, что она сохраняется после генерации тела представления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...