要求字典包含某些值(Swift)

时间:2018-11-05 04:58:50

标签: ios swift firebase google-cloud-firestore

我正在创建一个用于将用户数据保存到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 :(得分:0)

使用可选值构造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]

答案 1 :(得分:0)

在实时数据库中,如果您只想更新子项,请使用 updateChildValues 而不是setValue。我相信Firestore中有类似的东西。

实时数据库答案:

更新

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)")
    }
}

因此,经验法则是仅传递需要更新的字段,而不传递整个馆藏/词典。