Возникли проблемы при загрузке пользовательских данных из Firebase с помощью Swift - PullRequest
2 голосов
/ 12 февраля 2020

Я следовал инструкциям на веб-сайте Firebase и придумал код под названием NEW CODE. Я получаю сообщение об ошибке:

Невозможно вызвать инициализатор для типа 'Result' со списком аргументов типа '(@escaping () throws -> CombinedModel?)'

Я попытался исследовать об объекте Result и об этой ошибке, но не нашел ничего, что помогло бы мне напрямую. Я смог прочитать данные, используя старый способ (который я опубликую ниже), но я пытаюсь следовать документации Googles (https://firebase.google.com/docs/firestore/query-data/get-data)

Любая помощь будет оценена, спасибо you!

СТАРЫЙ КОД

func readData(word: String) -> CombinedModel? {
        print("reading data")
        let docRef = db.collection(K.FBConstants.dictionaryCollectionName).document(word)
        var wordResults: CombinedModel? = nil

        docRef.getDocument { (document, error) in
            if let e = error {
                print("Error loading data: \(e)")
                return
            } else {

                do {
                    if let resultData = try document?.data(as: CombinedModel.self){
                        print("Definitions: \(resultData.definitionsArray)")
                        print("\n Synonyms: \(resultData.synonyms)")
                        wordResults = resultData
                    }
                } catch {
                    print("Error decoding: \(error)")
                }
            }
        }
        return wordResults
    }

НОВЫЙ КОД

    func newReadData(word: String) -> CombinedModel? {
        let docRef = db.collection(K.FBConstants.dictionaryCollectionName).document(word)

        docRef.getDocument { (document, error) in
            let result = Result {
                try document.flatMap {
                    try $0.data(as: CombinedModel.self)
                }
            }
            switch result {
            case .success(let combinedModel):
                if let combinedModel = combinedModel {
                    print("CombinedModel: \(combinedModel)")
                } else {
                    print("Document does not exist")
                }
            case .failure(let error):
                print("Error decoding city: \(error)")
            }
        }
    }

Вот кодируемый пользовательский класс, который я создал для чтения данных.

struct CombinedModel: Codable {
    var definitionsArray: [WordModel]
    var synonyms: [String]

    private enum CodingKeys: String, CodingKey {
        case definitionsArray
        case synonyms
    }
}

struct WordModel: Codable {

    let id: String
    let partOfSpeech: String
    let definitions: [String]
    let example: [String]
    let ipa: String
    let audio: String

    private enum CodingKeys: String, CodingKey {
        case id
        case partOfSpeech
        case definitions
        case example
        case ipa
        case audio
    }
}

struct ThesaurusModel: Codable {

    var synonyms: [String]

    private enum CodingKeys: String, CodingKey {
        case synonyms
    }
}

Ответы [ 2 ]

1 голос
/ 12 февраля 2020

Я понял, что проблема с объектом Result заключалась в том, что XCode считывал его как структуру, которую я создал в другом файле, но как только я изменил имя этой структуры (ранее она называлась Result), он распознал объект Result. как правильный объект, который имеет тип: enum Результат где Ошибка: Ошибка

0 голосов
/ 12 февраля 2020

Похоже, вы приближаетесь - минус ошибка типа. Из того, что я могу сказать, ваша ошибка:

Cannot invoke initializer for type 'Result' with an argument list of type '(@escaping () throws -> CombinedModel?)'

Относится к этой части кода:

let result = Result {
    try document.flatMap {
        try $0.data(as: CombinedModel.self)
    }
}

По крайней мере, это часть кода, которая смотрит на меня Ваша переменная (document, error) в целом представляет ваш результат. Вам не нужен Result посредник.

Реальный фокус должен быть вокруг определения, есть ли ошибка. Если нет, вам следует прочитать документ.

Рабочий подход должен выглядеть примерно так:

func newReadData(word: String) -> CombinedModel? {
    let docRef = db.collection(K.FBConstants.dictionaryCollectionName).document(word)

    docRef.getDocument { (document, error) in
        guard let fbDoc = document else {
            // document is nil, parse the error object and handle it.
        }

        if let resultData = try fbDoc?.data(as: CombinedModel.self) {
            return resultData
        } else {
            return nil
        }
    }
}

Дайте мне знать, как это будет для вас! Желаем удачи.

...