Как получить файл Swift, который запускает запросы к БД и возвращает переменные из представлений

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

Я создал класс в том же представлении, в котором показываю данные в приложении, и он работает. Но когда я перемещаю его в отдельный быстрый файл, он выдает следующую ошибку:

struct ContentView: View {
    var body: some View {
        Home()

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


struct Home : View {
    @ObservedObject var categories = getCategoriesData()

    var body: some View { 
// Error: Unable to infer complex closure return type; add explicit type to disambiguate
        VStack {
            List(categories.datas) { i in
                Text(i.name)
            }
        }

    }
}

Swift файл:

class getCategoriesData : ObservableObject {
    @Published var datas = [category]()

    init () {
        let db = Firestore.firestore()

        db.collection("ingredients").addSnapshotListener{ (snap, err) in

            if err != nil {
                print((err?.localizedDescription)!)
                return
            }
            for i in snap!.documentChanges {
                let id = i.document.documentID
                let name = i.document.get("name") as! String

                self.datas.append(category(id: id, name: name))
            }
        }


    }
}

struct category : Identifiable {
    var id : String
    var name : String


}

Чтобы быть ясным, сейчас я получаю данные из ingredients категория в Firebase, я хочу повторно запустить класс и сохранить результат каждой категории в массиве / карте datasв этом случае я могу получить к ним доступ в разных представлениях. ИЛИ иметь его в другом классе, поэтому для каждого представления я запускаю запрос БД и получаю данные для одной из категорий.

Есть идеи, как заставить это работать?

Благодарность

1 ответ

Мне удалось скомпилировать ваш код, но на панели предварительного просмотра говорилось, что не удалось отобразить представление из-за сбоя компилятора.

Основная проблема с вашим кодом, похоже, заключается в том, что код доступа к данным находится в вашем инициализаторе. Я бы не рекомендовал это делать. Вместо этого извлеките этот фрагмент кода в методfetchDataи вызовите это, как только появится ваше представление. Например так:

import SwiftUI
import Firebase

struct ContentView: View {
  var body: some View {
    Home()
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}


struct Home : View {
  @ObservedObject var viewModel = CategoryViewModel()

  var body: some View {
    VStack {
      List(viewModel.categories) { category in
        Text(category.name)
      }
      .onAppear() {
        self.viewModel.fetchData()
      }
    }
  }
}
import Foundation
import FirebaseFirestore

struct Category : Identifiable {
  var id : String
  var name : String
}

class CategoryViewModel: ObservableObject {
  @Published var categories = [Category]()

  func fetchData() {
    let db = Firestore.firestore()

    db.collection("ingredients").addSnapshotListener{ (snapshot, err) in
      guard let documents = snapshot?.documents else {
        print("No documents")
        return
      }
      self.categories = documents.map { documentSnapshot in
        let id = documentSnapshot.documentID
        let name = documentSnapshot.get("name") as! String
        return Category(id: id, name: name)
      }
    }
  }
}

Вы заметите, что я также очистил именование (я бы порекомендовал прочитать руководства по стилю Рэя Вендерлиха и Google для Swift) и преобразовал ваш код сопоставления вmap - это упрощает чтение и делает его немного безопаснее.

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

Другие вопросы по тегам