我设计了我的代码,这样Firebase就不会被我的api服务(例如CurrentUserAPIService
(覆盖,所以如果我想更新用户对象,我想执行以下操作:
// CurrentUserAPIService.swift
func updateCurrentUser(with currentUser: CurrentUser, completionHandler: @escaping (Result<CurrentUser, APIError>) -> Void) {
myAPI.updateObject(object: currentUser, withId: currentUser.id, atPath: .users) { result in
switch result {
case .success:
print("Success")
completionHandler(.success(currentUser))
case .failure(let error):
print("Error: (error.localizedDescription)")
completionHandler(.failure(error))
}
}
}
它将调用我的API类来执行以下操作:
// MyAPI.swift
func updateObject<T: Encodable>(object: T, withId objectId: String, atPath path: Path, completionHandler: @escaping (Result<Void, APIError>) -> Void) {
let documentReference = Firestore.firestore().collection(path.rawValue).document(objectId)
do {
try documentReference.updateData(object, completion: { error in
if let error = error {
print("Error: (error.localizedDescription)")
completionHandler(.failure(.generic(message: error.localizedDescription)))
} else {
completionHandler(.success(()))
}
})
} catch {
print("Error: (error.localizedDescription)")
completionHandler(.failure(.generic(message: error.localizedDescription)))
}
}
这可能吗?如果可能的话,我想要一种方法来传递完整的对象,并让一个助手函数来计算实际要自动上传的内容。
如果您确实需要使用updateData语法,您应该围绕setData()
编写一个包装器。Firestore没有办法知道你想要更新什么。merge:true
将确保本地副本上的任何字段覆盖数据库副本。它不会从数据库中删除任何字段。
extension DocumentReference {
func updateData<T: Encodable>(for object: T, completion: @escaping (Error?) -> Void) {
do {
try self.setData(from: object, merge: true) { err in
completion(err)
}
} catch {
completion(error)
}
}
}