【发布时间】:2020-02-27 20:09:56
【问题描述】:
当 currentUser 点击likeButton 时,我会运行一个事务,但我想检查用户是否已经喜欢该帖子。如果用户已经喜欢了帖子,我想减少likeCounter并改变likeButton的外观,否则我想增加它。
我的 Firestore 数据库使用了 collection.document.collection.document.... 的东西:
"posts":
- "post1":
- uid: user1
- likeCount: 2
- caption: "caption1"
- "likes":
- "user1":
- value: true
- "user2":
- value: true
- "post2":
- uid: user1
- likeCount: 1
- caption: "caption2"
- "likes":
- "user1":
- value: true
- "user4":
- value: true
- "post3":
- uid: user2
- likeCount: 3
- caption: "caption3"
- "likes":
- "user1":
- value: true
- "user3":
- value: true
- "user4":
- value: true
这是我的 incrementLikes() 函数,每当用户点击 likeButton 时都会调用该函数
func incrementLikes() {
let ref = Api.Post.REF_POSTS.document(self.post!.id!)
Firestore.firestore().runTransaction({ (transaction, errorPointer) -> Any? in
let sfDocument: DocumentSnapshot
do {
try sfDocument = transaction.getDocument(ref)
} catch let fetchError as NSError {
errorPointer?.pointee = fetchError
return nil
}
guard let oldLikes = sfDocument.data()?["likeCount"] as? Int else {
let error = NSError(
domain: "AppErrorDomain",
code: -1,
userInfo: [
NSLocalizedDescriptionKey: "Unable to retrieve likes from snapshot \(sfDocument)"
]
)
errorPointer?.pointee = error
return nil
}
transaction.updateData(["likeCount": oldLikes - 1], forDocument: ref)
if let currentUser = Auth.auth().currentUser {
ref.collection(K.likesCollection).document(currentUser.uid).delete()
}
DispatchQueue.main.async {
self.likeImageView.image = UIImage(systemName: K.heart)
self.likeImageView.tintColor = UIColor.black
}
return nil
}) { (object, error) in
if let error = error {
print("Transaction failed: \(error)")
} else {
print("Transaction successfully committed!")
}
}
}
我想知道我的数据库是否以最可扩展的正确方式构建,以及我应该在哪里以及如何放置观察者以查看用户是否已经喜欢该帖子。
【问题讨论】:
-
这个问题有点不清楚。如果您想检查用户是否喜欢该帖子 - 这可以通过观察SingleEvent 用户喜欢该键的帖子来完成,如果它存在则减少帖子的likeCounter。您实际上甚至不需要查询,因为您知道帖子 ID 以查看它是否存在。入门指南Read Data Once 中介绍了读取数据。如果这不是你要问的,你能澄清一下这个问题吗?
-
感谢您的回答,但我使用的是 Firestore 而不是实时数据库,因此无法使用 observingSingleEvent 方法,有什么方法可以使用 Firestore 实现它吗?
-
另外,我应该将观察者放在 runTransaction 方法的哪个位置?再次感谢
-
哎呀,对不起。其实Firestore中也有获取一次数据的概念见Get Data Once,用法类似。获取文档,如果它存在(document.exists)然后减少likeCounter。此外,您不需要在 Firebase 闭包中使用此 DispatchQueue.main.async,因为 UI 调用在主线程上运行,而网络调用在后台线程上自动运行。
标签: ios swift firebase google-cloud-firestore transactions