我查看了几个小时的代码和备注,并且我正在努力寻找任何可以帮助我在使用firebase的swift应用程序中对一个对象进行upvoting和downvoting的文档。
我有一个照片库,我希望为图片添加一个Instagram风格的upvote。用户已经使用firebase auth登录,因此我有他们的用户ID。
我只是在努力想出这个方法以及需要在firebase中设置哪些规则。
任何帮助都会很棒。
答案 0 :(得分:12)
我将介绍如何使用Swift
和Firebase
在社交网络应用Impether中实现此类功能。
由于上升和下调是类似的,我将仅描述上升。
一般的想法是将一个upvotes计数器直接存储在与计数器相关的图像数据相对应的节点中,并使用事务写入更新计数器值,以避免数据不一致。
例如,假设您在路径/images/$imageId/
存储单个图像数据,其中$imageId
是用于标识特定图像的唯一ID - 例如,可以通过函数{生成{ {3}}包含在Firebase for iOS中。然后,对应于该节点上的单个照片的对象看起来像:
$imageId: {
'url': 'http://static.example.com/images/$imageId.jpg',
'caption': 'Some caption',
'author_username': 'foobarbaz'
}
我们想要做的是向此节点添加一个upvote计数器,因此它变为:
$imageId: {
'url': 'http://static.example.com/images/$imageId.jpg',
'caption': 'Some caption',
'author_username': 'foobarbaz',
'upvotes': 12,
}
当您创建新图像时(可能是在用户上传图像时),您可能希望使用0
或其他常量来初始化upvote计数器值,具体取决于您想要实现的目标。
当涉及更新特定的upvotes计数器时,您希望使用事务以避免其值的不一致(当多个客户端想要同时更新计数器时,可能会发生这种情况。)
幸运的是,处理Firebase
和Swift
中的事务性写入非常简单:
func upvote(imageId: String,
success successBlock: (Int) -> Void,
error errorBlock: () -> Void) {
let ref = Firebase(url: "https://YOUR-FIREBASE-URL.firebaseio.com/images")
.childByAppendingPath(imageId)
.childByAppendingPath("upvotes")
ref.runTransactionBlock({
(currentData: FMutableData!) in
//value of the counter before an update
var value = currentData.value as? Int
//checking for nil data is very important when using
//transactional writes
if value == nil {
value = 0
}
//actual update
currentData.value = value! + 1
return FTransactionResult.successWithValue(currentData)
}, andCompletionBlock: {
error, commited, snap in
//if the transaction was commited, i.e. the data
//under snap variable has the value of the counter after
//updates are done
if commited {
let upvotes = snap.value as! Int
//call success callback function if you want
successBlock(upvotes)
} else {
//call error callback function if you want
errorBlock()
}
})
}
上面的剪辑实际上几乎就是我们在制作中使用的代码。我希望它可以帮助你:)
答案 1 :(得分:1)
自己不是一个斯威夫特家伙(双关语!)但我认为this stackoverflow question有你的大部分答案。
然后,您只需使用几个if语句,根据您是要投票还是投票来从交易中返回正确的值。
答案 2 :(得分:1)
我非常惊讶,但原始文档中的this code就像一个魅力。它有一个缺点:如果有很多喜欢的话,json会变得非常大。
FirebaseService.shared.databaseReference
.child("items")
.child(itemID!)
.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in
if var item = currentData.value as? [String : AnyObject] {
let uid = SharedUser.current!.id
var usersLikedIdsArray = item["liked_who"] as? [String : Bool] ?? [:]
var likesCount = item["likes"] as? Int ?? 0
if usersLikedIdsArray[uid] == nil {
likesCount += 1
usersLikedIdsArray[uid] = true
self.setImage(self.activeImage!, for: .normal)
self.updateClosure?(true)
} else {
likesCount -= 1
usersLikedIdsArray.removeValue(forKey: uid)
self.setImage(self.unactiveImage!, for: .normal)
self.updateClosure?(false)
}
item["liked_who"] = usersLikedIdsArray as AnyObject?
item["likes"] = likesCount as AnyObject?
currentData.value = item
return TransactionResult.success(withValue: currentData)
}
return TransactionResult.success(withValue: currentData)
}) { (error, committed, snapshot) in
if let error = error {
self.owner?.show(error: error)
}
}