Сопоставить данные из Firestore со структурой в Swift - IOS - PullRequest
0 голосов
/ 13 января 2019

Я пытаюсь сопоставить «пользователя», полученного из моей базы данных Firestore, с пользовательской структурой, которую я определил в своем коде, но не думаю, что правильно понимаю функции отображения в swift.

Как мне отобразить пользователя, полученного в структуру?

Struct

struct User {
// Properties

    var firstName: String
    var lastName: String
    var userName: String
    var email: String

    init(firstName: String, lastName: String, userName: String, email: String) {
        self.firstName = firstName
        self.lastName = lastName
        self.userName = userName
        self.email = email
    }
}

Функция, которая получает пользователя из Firestore

func getUser(UID: String) {
    // Firebase setup
    settings.areTimestampsInSnapshotsEnabled = true
    db.settings = settings

    db.collection("users").document(UID).getDocument { (document, error) in
        if let error = error {
            print("Error: \(error.localizedDescription)")
        } else {
            print(document!.data()!)
        }
    }
}

1 Ответ

0 голосов
/ 13 января 2019

Запрашиваемый документ Firestore имеет тип [String: Any], поэтому настройте инициализатор так, чтобы он принимал такой словарь. Поскольку вы работаете с возвратом из базы данных, никогда не гарантируется, что данные будут полностью сохранены; сетевые ошибки и ошибки базы данных могут вернуть отсутствующие или поврежденные данные. Поэтому рекомендуется отключить инициализатор - это просто означает, что он может вернуть nil (может произойти сбой).

Я взял ваш пример и сделал свойство email необязательным, просто чтобы показать вам, как это будет выглядеть. В приведенном ниже примере только три из четырех свойств необходимы для создания экземпляра объекта User.

let info: [String: Any] = ["hasFriends": true]
let firestoreData: [String: Any] = ["firstName": "lance", "lastName": "stevenson", "userName": "lstevenson", "info": info]

struct User {

    var firstName: String
    var lastName: String
    var userName: String
    var info: [String: Any]
    var email: String?
    var hasFriends: Bool

    init?(data: [String: Any]) {

        guard let firstName = data["firstName"] as? String,
            let lastName = data["lastName"] as? String,
            let userName = data["userName"] as? String,
            let info = data["info"] as? [String: Any],
            let hasFriends = info["hasFriends"] as? Bool else {
                return nil
        }

        self.firstName = firstName
        self.lastName = lastName
        self.userName = userName
        self.info = info
        self.hasFriends = hasFriends
        self.email = data["email"] as? String // User will be created even if this is nil

    }

}

if let user = User(data: firestoreData) {
    print(user.hasFriends)
}

// prints true

Я бы не советовал использовать для этого инструмент сопоставления Swift, потому что вы, вероятно, будете иметь дело с разными типами значений в одном и том же словаре для разных объектов модели. И код для сопоставления словаря [String: Any] с этими переменными в инициализаторе не будет красивым, особенно если учесть, что альтернатива (здесь) дает тот же результат со значительно более простым кодом.

Помните, утопия программирования - то, к чему мы все должны стремиться - это выполнять самые мощные вещи с помощью максимально простого кода. Если это не цель, то так и должно быть.

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