ios - Swift:只允许用户对 TableViewCell 中的项目投票一次

标签 ios swift parse-platform

所以我制作了一个类似于 Yik Yak 中的新闻提要,用户可以在其中发布内容,其他用户可以对该帖子投赞成票或反对票。我正在将这个函数与 Parse 集成,并且我已经成功地制作了上传到 Parse 的赞成票和反对票函数(遵循此处的教程:http://shrikar.com/parse-backed-uitableview-in-ios-8-build-yik-yak-clone-part-2/)。不幸的是,我正在努力弄清楚如何让用户只能投票赞成/反对一次。

我最初的想法是创建本地存储的 bool 值,用于判断用户是否投了赞成票或反对票,并使用 if/else 语句来确定用户是否可以再次投赞成票/反对票。这使我得到了以下代码(IBActions 连接到用于赞成和反对的按钮):

class TableViewController: PFQueryTableViewController {

var hasUpvoted: Bool?
var hasDownvoted: Bool?

@IBAction func yellUpvote(sender: AnyObject) {
      let hitPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let hitIndex = self.tableView.indexPathForRowAtPoint(hitPoint)
    let object = objectAtIndexPath(hitIndex)
    object!.incrementKey("voteCount")
    object!.saveInBackground()
    self.tableView.reloadData()
    NSLog("Top Index Path \(hitIndex?.row)")



    if (hasUpvoted == true) {
        println("Do nothing, A")
    }


    if (hasUpvoted == false) {
        if (hasDownvoted == true){
            println("Add two points, B")
            hasUpvoted = true
            hasDownvoted = false
        }


        }

        if (hasUpvoted == nil){
            if (hasDownvoted == true){
                println("Add 2 pts, E")
                hasUpvoted = true
                hasDownvoted = false
            }

            if (hasDownvoted == nil){
                println("Add 1 point, G")
                hasUpvoted = true
            }
    }


}


@IBAction func yellDownvote(sender: AnyObject) {

        let hitPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let hitIndex = self.tableView.indexPathForRowAtPoint(hitPoint)
    let object = objectAtIndexPath(hitIndex)
    object!.incrementKey("voteCount", byAmount: -1)
    object!.saveInBackground()
    self.tableView.reloadData()
    NSLog("Bottom Index Path \(hitIndex?.row)")

    if (hasDownvoted == true) {
        println("do nothing, H")
    }


    if (hasDownvoted == false) {


        if (hasUpvoted == true){
            println("downvote 2, J")
            hasDownvoted = true
            hasUpvoted = false
        }

    }

    if (hasDownvoted == nil){
        if (hasUpvoted == true){
            println ("downvote 2, L")
            hasDownvoted = true
            hasUpvoted = false
        }



        if (hasUpvoted == nil) {
            println ("downvote 1, N")
            hasDownvoted = true
            hasUpvoted = false
        }
    }
}

我很快意识到,这些 bool 值并不是 TableView 中给定单元格所独有的,所以如果我对帖子 A 投赞成票,并想对帖子 B 投赞成票, bool 值将被设置为好像我已经对帖子 B 投了赞成票一样。第二个问题是,这些将在用户关闭应用程序时重置为 nil,从而允许他们对同一个帖子进行多次投票。

我的下一个想法是使用以下代码使 bool 值专用于给定的单元格:

    let hitPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let hitIndex = self.tableView.indexPathForRowAtPoint(hitPoint)

虽然我不知道该怎么做。此外,这不会解决用户能够简单地关闭应用程序以重新获得再次投票能力的问题。

那么,对于如何让用户只能投票一次,有没有人有解决方案?

最佳答案

好的,所以我找到了一个可接受的解决方案。这集成了 Parse,并且只允许用户投票和撤回投票(而不是投票)。然而,可以按照与我选择的方法类似的方法来实现向下投票(尽管有更多的 if/else 语句)。

类 TableViewController: PFQueryTableViewController {

var hasUpvoted: Bool?

@IBAction func postUpvote(sender: AnyObject) {

    let hitPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let hitIndex = self.tableView.indexPathForRowAtPoint(hitPoint)
    let object = objectAtIndexPath(hitIndex)

    var hasVotedQuery = PFQuery(className:"Posts")
    hasVotedQuery.getObjectInBackgroundWithId(object!.objectId!) {
        (post: PFObject?, error: NSError?) -> Void in
        if error != nil {
            println(error)
        } 
        else if let post = post {

            var usersHaveUpvotedArray = post["usersHaveUpvoted"] as? NSArray
            println(usersHaveUpvotedArray)
            var userObjectId = PFUser.currentUser()?.objectId as String!

            let contained = contains(usersHaveUpvotedArray! as! Array, userObjectId)

            if (contained == true) {
                post.removeObject(userObjectId, forKey: "usersHaveUpvoted")
                post.saveInBackground()
                object!.incrementKey("voteCount", byAmount: -1)
                object!.saveInBackground()
                self.tableView.reloadData()
            }

            if (contained == false) {
                post.addUniqueObject(userObjectId, forKey: "usersHaveUpvoted")
                post.saveInBackground()
                object!.incrementKey("voteCount")
                object!.saveInBackground()
                self.tableView.reloadData()
            }
        }
    }
}

IBAction 链接到投票按钮。 “帖子”是包含帖子的 Parse 类。 “usersHaveUpvoted”是一个数组,其中包含对给定帖子投了赞成票的用户的 objectId。请注意,如果 usersHaveUpvoted 数组为零,我的代码将导致应用程序崩溃。我的解决方案是在上传帖子时自动在 usersHaveUpvoted 数组中放置一个值。不过,可能有更优雅的方法来解决该问题。

但唯一的另一个问题是,如果用户足够快地按了两次投票按钮,则有可能在手机收到用户已经投票的消息之前投票两次。使用本地数据存储可能是一种聪明的方法。

关于ios - Swift:只允许用户对 TableViewCell 中的项目投票一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31308764/

相关文章:

ios - UITableView 动态单元格高度冲突 - 高度不依赖于标签

ios - iOS 设备上的 Safari 正在加载损坏的图像 - Wordpress 网站

api - 无法使用 Parse Schema API 创建具有指针类型字段的类

android - 将现有用户与 Facebook 帐户关联的正确方法

ios - 如何删除 GPPSignInButton 的默认样式(文本、G+ 图像)以在 iOS 中添加您自己的样式

ios - 如何使用AFNetworking将nsdata下载到内存

swift - 突然找不到 header 中的 header <module-includes> :1:9: note: in file included from <module-includes>:1: Xcode

json - 如何将 Swift 对象序列化或转换为 JSON?

ios - 尝试快速实现发布者/订阅者

ios - 只能在符合 PFSubclassing 的子类上调用 -[PFObject init]