Возвращает массив базы данных Firebase другой функции, но возвращает пустой

#database #firebase #swiftui #completionhandler

# #База данных #Firebase #SwiftUI #завершениеhandler

Вопрос:

Я создаю приложение Cue Card. Я добавил свою базу данных в массив, но при вызове этого массива в другой функции (где я хочу внести изменения в массив) он возвращает пустой. Я провел много поисков по этой теме и обнаружил, что должен использовать обработчик завершения, что, я думаю, я и сделал. Существует много информации по этой теме, например https://firebase.googleblog.com/2018/07/swift-closures-and-firebase-handling.html но, похоже, я не могу заставить это работать в моем приложении. Вид Cue Card:

 import SwiftUI

struct CueCardView: View {

var viewModel = CueCardViewModel()
@State private var isShowingAnswer = false

var body: some View {
    ZStack{
        RoundedRectangle(cornerRadius: 25, style: .continuous)
            .fill(Color.white)
        VStack{
              Text("heloo")
                .onAppear{
                    self.viewModel.initializeCues()
                }
        }
        .padding(20)
        .multilineTextAlignment(.center)
    }
    .onTapGesture {
        self.isShowingAnswer.toggle()
    
    }
    
}


}

struct C1_Previews: PreviewProvider {
static var previews: some View {
    
    CueCardView().previewDevice("iPhone 12")
}

}
 

Модель Cue Card:

 import SwiftUI

struct CueCardModel : Identifiable {
var id: String = UUID().uuidString
var term: String
var answer: String
}
 

Загрузка данных :

 import SwiftUI
import Firebase

var dbRef = Firestore.firestore()
struct DataDownloader {
func downloadCues(completion: @escaping ([CueCardModel]) -> Void) {
    var array = [CueCardModel]()
    dbRef.collection("Cues").getDocuments(){(snap, err) in
        if let err = err {
            print(err)
        } else {
            guard let snap = snap else {return}
            
                for doc in snap.documents {
                let id = doc.documentID
                let term = doc.get("term") as! String
                let answer = doc.get("answer") as! String
                let cue = CueCardModel(id: id, term: term, answer: answer)
                array.append(cue)
            }
            completion(array)
        }
    }
}
}
 

Модель просмотра Cue Card:

 import SwiftUI
import Firebase

class CueCardViewModel: ObservableObject {

let dataDownloader = DataDownloader()

func initializeCues() {
    dataDownloader.downloadCues() { array in
        print(array)
    }
    
}
}
 

Комментарии:

1. Вы должны добавить операторы печати во все функции и посмотреть, где это происходит. Я бы начал с добавления print в начале downloadCues, чтобы убедиться, что он вызывается.. другая печать в функции, где вы проверяете значения привязки.. и, вероятно, один в начале initializeCues, чтобы убедиться, что он вызывается. Просто взгляните быстро, возможно, вам потребуется добавить init() в CueCardViewModel, чтобы фактически вызвать initializeCues ?

2. Отличное предложение, которое я всегда упускаю из виду. Похоже, что он не запускает for doc в цикле snap.documents {} в файле DataDownloader.

3. Доходит ли это до инструкции «guard let snap = snap else {return}»? Я предполагаю, что он возвращается туда. Это означало бы, что функция не получает снимок в DBRef.collection(«Подсказки»). Убедитесь, что вы обращаетесь к правильному пути / коллекции. Я считаю, что он чувствителен к регистру («сигналы» против «сигналов»).

4. И вы читаете мысли! Моя коллекция базы данных была названа «Cue», а не «Cues». Я работал над этим около 4 часов. Спасибо!

5. Ха-ха, я сам сталкивался с подобными проблемами. Я также опубликовал ответ с рекомендацией для вас. Приветствия!

Ответ №1:

Убедитесь, что путь запроса точно такой же, как вы настроили его в Firebase. Я бы рекомендовал создать структуру для имен всех ваших коллекций (и, возможно, дополнительные структуры для каждого поля в каждой коллекции), чтобы избежать ввода явных строк при выполнении запросов. Также обычной практикой является сохранение всех полей базы данных в нижнем регистре, чтобы избежать проблем с учетом регистра строк. Например:

Создайте глобальную структуру с коллекцией:

 struct DatabaseCollections {
    static let cue = "cue"
    static let nextCollection = "collection_two"
}
 

Использование:

 dbRef.collection(DatabaseCollections.cue).getDocuments...