SwiftUI: поиск наилучшего способа сопоставления ответа API - PullRequest
0 голосов
/ 09 ноября 2019

Я начинаю изучать SwiftUI. Сейчас я думаю о наилучшем способе сопоставления ответа API в ObservableObject.

Прежде всего, это ответ API:

{
    "food": [
        "fish",
        "meat"
    ],
    "go": [
        "London",
        "Bangkok"
    ],
    "party": [
        "Family",
        "Friends"
    ]
}

Это мой ObservableObject:

struct MyViewModel: ObservableObject {

    var food: [String]
    var go: [String]
    var party: [String]

    func fetchTagMeResponse() {
        let url = URL(string: "domain.com/api/tagmes/")
        var result = nil
        URLSession.shared.dataTask(with: url!) { (data, res, err) in
            DispatchQueue.main.async {
               // WHAT IS THE BEST WAY TO MAP IT?
            }
        }.resume()
        return result
    }

}

Как видите, мне нужен лучший способ обработки ответа на данные после получения его из API в строке кода:

DispatchQueue.main.async {
   // WHAT IS THE BEST WAY TO MAP IT?
}

Мое решение

Я думаю об использовании Decodable и думаю, что это не лучший способ. Потому что, если я больше не буду использовать MyResponse. Это не нужно?

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

Скажите, есть ли у вас, ребята, лучшее решение для этого.

Ответы [ 2 ]

1 голос
/ 09 ноября 2019

Вы можете использовать Combine для этого. Кстати, лучше использовать Codable, так как он сделан Apple, чтобы снять тяжелую работу для вас. Это мощный инструмент.

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()
    }
  }
}
1 голос
/ 09 ноября 2019

Вот мой класс NetworkManager, для меня он лучший подход для обработки API в SwiftUI

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

// Вот как я связываю данные.

struct ContentView: View {
    @ObservedObject var networkManager = NetworkManager()


    var body: some View {
        NavigationView {
            List {
                ForEach(networkManager.courses, id: \.id) { course in
                    RowUI(course: course)
                }
            }
            .navigationBarTitle(Text("Courses"))
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...