Разбор данных JSON из Firebase Swift - PullRequest
0 голосов
/ 28 ноября 2018

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

enter image description here

Я пытаюсь получитьДанные из базы данных и назначить их экземпляру класса Meal:

ref = Database.database().reference()
        databaseHandle = ref.child("Meal").observe(.value, with: { (snapshot) in
            var downloadedName : String!
            var downloadedPhoto : String!
            var downloadedRating : Int!
            var downloadedSteps : Array <String>!
            var downloadedIngredients : [Dictionary <String, String>]!

            print(snapshot.value)
            if let dict = snapshot.value as? Dictionary<String, Any>{
                print("VALUES!!!")


                for key in dict.keys {

                    if let values = dict[key] as? Dictionary<String, Any> {
                        print(values)

                        if let name = values["name"] as? String{
                            downloadedName = name
                        }

                        if let photo = values["photo"] as? String{
                            downloadedPhoto = photo
                        }

                        if let rating = values["rating"] as? Int{
                            downloadedRating = rating
                        }
                        if let steps = values["steps"] as? Array<String>{
                            downloadedSteps = steps
                        }
                        if let ingredients = values["ingredients"] as? [Dictionary <String, String>]{
                            downloadedIngredients = ingredients
                        }

                         let meal = Meal(name: downloadedName, photo: UIImage(named: downloadedPhoto), rating: downloadedRating, steps: downloadedSteps, ingredients: downloadedIngredients)           
                        self.meals.append(meal!);
                    }
                }

Сам класс еды выглядит так:

class Meal {
    var name: String
    var photo: UIImage?
    var rating: Int
    var steps: Array<String>
    var ingredients: [Dictionary<String, String>]}

Я получаю первое print - целоеданные, поэтому связь с БД в порядке, но когда я пытаюсь назначить его - ничего не происходит, нет ошибок, нет данных (второй print с сообщением VALUES!!! вообще не отображается, что я делаю неправильно?

Вот также то, что я получаю сначала print

Optional(<__NSArrayM 0x600002fdaa60>(
{
    ingredients =     (
                {
            amount = 100;
            ingredient = milk;
            measurement = ml;
        },
                {
            amount = 120;
            ingredient = milk;
            measurement = ml;
        }
    );
    name = "Caprese Salad";
    photo = meal1;
    rating = 4;
    steps =     (
        test1,
        test11
    );
},
{
    ingredients =     (
                {
            amount = 100;
            ingredient = milk;
            measurement = ml;
        },
                {
            amount = 120;
            ingredient = milk;
            measurement = ml;
        }
    );
    name = "Chicken and Potatoes";
    photo = meal2;
    rating = 3;
    steps =     (
        test2,
        test22
    );
},
{
    ingredients =     (
                {
            amount = 100;
            ingredient = milk;
            measurement = ml;
        },
                {
            amount = 120;
            ingredient = milk;
            measurement = ml;
        }
    );
    name = "Pasta with Meatballs";
    photo = meal3;
    rating = 2;
    steps =     (
        test3,
        test33
    );
}
)
)

Итак, я предполагаю, что в какой-то момент я получаю данные ложным образом, как я могу это исправить?

1 Ответ

0 голосов
/ 28 ноября 2018

У вас есть:

print(snapshot.value)
if let dict = snapshot.value as? Dictionary<String, Any>{
    print("VALUES!!!")
    ....
}

Вы говорите, что print(snapshot.value) называется, но не print("VALUES!!!").Ну, это означает, что snapshot.value или это не Dictionary, ключи которого String, объекты и значения имеют тип Any.

Теперь давайте посмотрим на вывод snapshot.value:

Optional(<__NSArrayM 0x600002fdaa60> ...

NSArrayM => NSMutableArray, поэтому snapshot.value является Array, а не Dictionary.Конечно, тогда as? Dictionary потерпит неудачу!

Так что вам нужно рассматривать его как Array.

Быстро написано:

if let array = snapshot.value as? [[String: Any]] {
    for aValue in array {
        let name = aValue["name"] as? String ?? "unnamed"
        let photoName = aValue["photo"] as? String ?? "noPhoto"
        let rating = aValue["rating"] as? Int ?? 0
        let steps = aValue["steps"] as? [String] ?? []
        let ingredients = aValue["ingredients"] as? [[String: String]] ?? [:]
        let meal = Meal(name: name, photo: UIImage(named: photoName), rating: rating, steps: steps, ingredients: ingredients)           
        self.meals.append(meal)
    }
}

То, что также могло бытьнеправильно с вашим подходом:

var downloadedName : String!
loop {
    if let name = values["name"] as? String {
        downloadedName = name
    }
    let meal = Meal(name: downloadedName, ...)
}

Что ж, если для второго значения у вас нет имени (либо потому, что это не String, либо потому, что значение не существует), вы downloadedName будет иметь значение первого, но остальные значения второго.

Я использовал подход:

let name = aValue["name"] as? String ?? "unnamed"

То есть, если он равен нулю, он получаетзначение по умолчанию.Но вы можете принять только один действительный, с помощью guard let или if let потенциально для всех подзначений.

Например:

if let name = aValue["name"] as? String,
   let let photoName = aValue["photo"] as? String, 
   ... {
    let meal = Meal(name: name, photo: UIImage(named: photoName)
    self.meals.append(meal)
}

А так как ваш Meal.init() кажетсячтобы вернуть необязательный параметр, вы можете добавить его также в if let и избежать принудительного развертывания meal.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...