Требовать словарь, содержащий определенные значения (Swift) - PullRequest
0 голосов
/ 05 ноября 2018

Я создаю модель для сохранения пользовательских данных в базе данных Firestore и инициализирую ее словарем. В зависимости от того, какие поля я хочу обновить, я помещаю эти значения в словарь, чтобы пользовательская модель содержала только определенные поля и поэтому обновляла только эти поля в моей базе данных. Однако я хочу как-то потребовать, чтобы определенные поля были предоставлены в определенных случаях использования.

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

Я уверен на 99%, что нападаю на это неправильно, поэтому любая помощь приветствуется.

Моя текущая модель:

struct FirestoreUser {
    var id: String
    var name: String?
    var profileImage: String?

    var dictionary: [String: Any]

    init(dictionary: [String: Any]) {
        self.id = dictionary["id"] as! String
        self.name = dictionary["name"] as? String
        self.profileImage = dictionary["profileImage"] as? String

        self.dictionary = dictionary
    }
}

// MARK: Firestore functions
extension FirestoreUser {
    typealias Handler = ((Error?) -> Void)?
    func saveNewFirestoreUser(then handler: Handler = nil) {
        // make sure all necessary variables are set
        // if they aren't all set, something went wrong
        guard let _ = name, let _ = profileImage else { return }

        let firestore = Firestore.firestore()
        let ref = firestore.collection("users").document(id)

        ref.setData(dictionary) { (error) in
            if let error = error {
                handler?(error)
            }
            handler?(nil)
        }
    }
}

Ответы [ 2 ]

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

В базе данных реального времени используйте updateChildValues ​​ вместо setValue, если вы просто хотите обновить дочерний элемент. Я считаю, что в пожарном магазине есть что-то эквивалентное.

Ответ для базы данных в реальном времени:

Обновление

self.ref.child("users/\(user.uid)/username").setValue(username)

Установить новые данные

let key = ref.child("posts").childByAutoId().key
let post = ["uid": userID,
            "author": username,
            "title": title,
            "body": body]
let childUpdates = ["/posts/\(key)": post,
                    "/user-posts/\(userID)/\(key)/": post]
ref.updateChildValues(childUpdates)

Ответ для пожарного магазина:

Просто прочитайте документацию для firestore, используйте updateData вместо addDocument:

let washingtonRef = db.collection("cities").document("DC")

// Set the "capital" field of the city 'DC'
washingtonRef.updateData([
    "capital": true
]) { err in
    if let err = err {
        print("Error updating document: \(err)")
    } else {
        print("Document successfully updated")
    }
}

Установить / добавить новые данные

// Add a new document with a generated id.
var ref: DocumentReference? = nil
ref = db.collection("cities").addDocument(data: [
    "name": "Tokyo",
    "country": "Japan"
]) { err in
    if let err = err {
        print("Error adding document: \(err)")
    } else {
        print("Document added with ID: \(ref!.documentID)")
    }
}

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

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

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

struct FirestoreUser: Codable {
    var id: String
    var name: String?
    var profileImage: String?
}


extension Encodable {
var dictionary: [String: Any]? {
    guard let data = try? JSONEncoder().encode(self) else { return nil }
    return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] }
}
}

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

let test = FirestoreUser(id: "01", name: "Abhinav", profileImage: nil)
print(test.dictionary)

Вывод -

["name": Abhinav, "id": 01]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...