SwiftUI:寻找映射API响应的最佳方法

SwiftUI:寻找映射API响应的最佳方法,swift,swiftui,Swift,Swiftui,我开始学习SwiftUI。现在,我正在考虑将API响应映射到ObservieObject中的最佳方法 首先,这是API响应: { "food": [ "fish", "meat" ], "go": [ "London", "Bangkok" ], "party": [ "Family", "Friends" ] } 这是我的观察对象: 如您所见,我需要

我开始学习SwiftUI。现在,我正在考虑将API响应映射到ObservieObject中的最佳方法

首先,这是API响应:

{
    "food": [
        "fish",
        "meat"
    ],
    "go": [
        "London",
        "Bangkok"
    ],
    "party": [
        "Family",
        "Friends"
    ]
}
这是我的观察对象:

如您所见,我需要在代码行中从API获取数据响应后处理数据响应的最佳方法:

DispatchQueue.main.async {
   // WHAT IS THE BEST WAY TO MAP IT?
}
我的解决方案


我正在考虑使用Decodable,我认为这不是最好的方法。因为如果我不再使用我的回应。没有必要吗

struct MyResponse: Decodable {
   var food: [String]
   var go: [String]
   var party: [String]
}

告诉我你们是否有更好的解决方案。

这是我的NetworkManager类,请告诉我它在SwiftUI中处理API的最佳方法

class NetworkManager: ObservableObject {
    var objectWillChange = PassthroughSubject<NetworkManager,Never>()

    var courses = [Course](){
        didSet{
            objectWillChange.send(self)
        }
    }

    init() {
        guard let url = URL(string: "https://myDomain/courses") else{ return }

        URLSession.shared.dataTask(with: url) { (data, response, error) in

            guard let data = data else { return }
            let courses = try! JSONDecoder().decode([Course].self , from: data)

            DispatchQueue.main.async {
                self.courses =  courses

                debugPrint(self.courses)
            }
        }.resume()
    }
}

这是我的NetworkManager类,请为我介绍它在SwiftUI中处理API的最佳方法

class NetworkManager: ObservableObject {
    var objectWillChange = PassthroughSubject<NetworkManager,Never>()

    var courses = [Course](){
        didSet{
            objectWillChange.send(self)
        }
    }

    init() {
        guard let url = URL(string: "https://myDomain/courses") else{ return }

        URLSession.shared.dataTask(with: url) { (data, response, error) in

            guard let data = data else { return }
            let courses = try! JSONDecoder().decode([Course].self , from: data)

            DispatchQueue.main.async {
                self.courses =  courses

                debugPrint(self.courses)
            }
        }.resume()
    }
}

您可以使用Combine来执行此操作。顺便说一句,最好使用Codable,因为它是由苹果公司生产的,可以帮你解除繁重的工作。这是一个强大的工具

import SwiftUI
import Combine

//MARK: - Your model
struct MyResponse: Identifiable, Codable {
  let id: Int
  var food: [String]
  var go: [String]
  var party: [String]
}

//MARK: - Your network manager
class NetworkManager: ObservableObject {

  @Published var myResponseFood = [String]()
  @Published var myResponseGo = [String]()
  @Published var myResponseParty = [String]()

  func fetchTagMeResponse() {
    _ = URLSession.shared
      .dataTaskPublisher(for: URL(string: "domain.com/api/tagmes/")!)
      .map(\.data)
      .decode(type: MyResponse.self, decoder: JSONDecoder())
      .sink(receiveCompletion: { (completion) in
        if case .failure(let error) = completion {
          print("You have an error: \(error)")
        }
      }, receiveValue: { (object) in
        //MARK: - Your map objects are here
        self.myResponseFood = object.food
        self.myResponseGo = object.go
        self.myResponseParty = object.party
      })
  }
}

//MARK: - Your SwiftUI view
struct MyViewModel: View {

  @ObservedObject var networkManager = NetworkManager()

  var body: some View {
    NavigationView {
      List(networkManager.myResponseParty) { party in
        Text(party)
      }
    }
    .onAppear {
      self.networkManager.fetchTagMeResponse()
    }
  }
}

您可以使用Combine来执行此操作。顺便说一句,最好使用Codable,因为它是由苹果公司生产的,可以帮你解除繁重的工作。这是一个强大的工具

import SwiftUI
import Combine

//MARK: - Your model
struct MyResponse: Identifiable, Codable {
  let id: Int
  var food: [String]
  var go: [String]
  var party: [String]
}

//MARK: - Your network manager
class NetworkManager: ObservableObject {

  @Published var myResponseFood = [String]()
  @Published var myResponseGo = [String]()
  @Published var myResponseParty = [String]()

  func fetchTagMeResponse() {
    _ = URLSession.shared
      .dataTaskPublisher(for: URL(string: "domain.com/api/tagmes/")!)
      .map(\.data)
      .decode(type: MyResponse.self, decoder: JSONDecoder())
      .sink(receiveCompletion: { (completion) in
        if case .failure(let error) = completion {
          print("You have an error: \(error)")
        }
      }, receiveValue: { (object) in
        //MARK: - Your map objects are here
        self.myResponseFood = object.food
        self.myResponseGo = object.go
        self.myResponseParty = object.party
      })
  }
}

//MARK: - Your SwiftUI view
struct MyViewModel: View {

  @ObservedObject var networkManager = NetworkManager()

  var body: some View {
    NavigationView {
      List(networkManager.myResponseParty) { party in
        Text(party)
      }
    }
    .onAppear {
      self.networkManager.fetchTagMeResponse()
    }
  }
}

我正在考虑使用Decodable,我认为这不是最好的方法。为什么不呢?如果我不再使用MyResponse,你应该使用Decodablei。没有必要吗?我正在考虑使用可解码,我认为这不是最好的方法。为什么不呢?如果我不再使用MyResponse,你应该使用Decodablei。没有必要吗?