ios - SWIFT:快速点击 UIButton 会导致选票计数不正确

标签 ios swift xcode7

我在下面创建了一个简单的歌曲列表应用程序。

enter image description here

其工作原理如下: 1. 用户可以将歌曲添加到列表中(使用“+”图标) 2. 用户可以点击投票按钮来增加或减少自己的投票。它的工作原理类似于 Facebook 上的“LIKE”按钮。

如您所见,部分票数为负数。原因是在质量检查期间,我极快地点击了“投票”按钮,导致投票计数失控。我不认为这种情况会经常发生,但是有人有创造性的方法来防止这种情况发生吗?任何解决方案将不胜感激。谢谢。

如果需要,我可以添加我的代码,但我希望有一个我尚未找到的简单解决方案。

更新:添加了 TableView Controller 和 TableView 单元格的代码 -

表格 View 单元格(带有“投票”的 UIButton 操作):

@IBAction func voteButton(sender: UIButton) {

    var query = PFQuery(className:"UserVotes")

    //query the database to check if the user actually like the song in the paticular row that's clicked
    query.whereKey("username", equalTo: (PFUser.currentUser()?.username)!)
    query.whereKey("song", equalTo: songID!)
    query.whereKey("vote", equalTo: true)

    query.findObjectsInBackgroundWithBlock {
        (object: [PFObject]?, error: NSError?) -> Void in

        if error == nil {

            //this is the case where a TRUE value is found. LIKE is ON
            if object!.count > 0 {

                if let object = object! as? [PFObject] {

                    for object in object {

                        if self.delegate != nil && self.rowValue != nil {

                            //decrease the count by 1
                            self.voteCount = self.voteCount! - 1
                            self.votes.text = "\(self.voteCount!)"

                            self.voteButtonOn = true
                            self.delegate!.voteButtonTurnOffFromCellRow(self.rowValue!)
                            print(self.voteButtonOn)
                        }

                    }
                }

            //this is the case where a TRUE value is NOT found, LIKE is OFF.
            } else if object?.count == 0 {

                if self.delegate != nil && self.rowValue != nil {

                    //increase the count by 1
                    self.voteCount = self.voteCount! + 1
                    self.votes.text = "\(self.voteCount!)"

                    self.voteButtonOn = false
                    self.delegate!.voteButtonTurnOnFromCellRow(self.rowValue!)
                    print(self.voteButtonOn)

                }
            }

        } else {
            // Log details of the failure
            print("Error: \(error!) \(error!.userInfo)")
        }
    }
}

TableView Controller :

import UIKit
import Parse

protocol VoteProtocol {
    func voteButtonTurnOnFromCellRow(row: Int)
    func voteButtonTurnOffFromCellRow(row: Int)
}

class MusicPlaylistTableViewController: UITableViewController, VoteProtocol {

var usernames = [String]()
var songs = [String]()
var songVotes = [Int]()

//Function to display an alert
func displayAlert(title: String, message: String) {

    let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
    self.presentViewController(alert, animated: true, completion: nil)

}

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.separatorColor = UIColor.grayColor()

    let query = PFQuery(className:"PlaylistData")
    query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) -> Void in

        if error == nil {

            if let objects = objects! as? [PFObject] {

                self.usernames.removeAll()
                self.songs.removeAll()

                for object in objects {

                    let username = object["username"] as? String
                    self.usernames.append(username!)

                    let track = object["song"] as? String
                    self.songs.append(track!)

                    let votes = object["numVotes"] as? Int
                    self.songVotes.append(votes!)                        
                }

                self.tableView.reloadData()
            }

        } else {

            print(error)
        }
    }


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1

}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return usernames.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("CellTrack", forIndexPath: indexPath) as! TrackTableViewCell

    cell.username.text = usernames[indexPath.row]
    cell.songTitle.text = songs[indexPath.row]

    var voteCount: Int = songVotes[indexPath.row]
    var voteCountString = String(voteCount)
    cell.votes.text = voteCountString

    cell.delegate = self
    cell.rowValue = indexPath.row
    cell.songID = songs[indexPath.row]
    cell.voteCount = songVotes[indexPath.row]

    cell.selectionStyle = UITableViewCellSelectionStyle.None
    return cell
}

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {



}

//If the LIKE button is OFF perform this. This means that a record in the database has NOT been found with a value of TRUE.
func voteButtonTurnOnFromCellRow(var row: Int) {

    // At this point, the value needs to be changed to TRUE, and the vote count needs to be increased by 1.
    //note: does not take into account scenario where there are duplicate records (slight case)
    let query = PFQuery(className:"UserVotes")
    query.whereKey("username", equalTo: (PFUser.currentUser()?.username)!)
    query.whereKey("song", equalTo: songs[row])
    query.whereKey("vote", equalTo: false)

    query.findObjectsInBackgroundWithBlock { (object: [PFObject]?, error: NSError?) -> Void in


        if error == nil {

            //this is the case where a FALSE value is found. LIKE is OFF
            if object!.count > 0 {

                if let object = object! as? [PFObject] {

                    for object in object {

                        object["vote"] = true
                        object.saveInBackground()

                        let query = PFQuery(className:"PlaylistData")
                        query.whereKey("song", equalTo: self.songs[row])

                        query.findObjectsInBackgroundWithBlock { (object: [PFObject]?, error: NSError?) -> Void in

                            if error == nil {

                                if let object = object! as? [PFObject] {

                                    for object in object {

                                        var voteCount:Int = object["numVotes"] as! Int
                                        voteCount = voteCount + 1
                                        object["numVotes"] = voteCount
                                        object.saveInBackground()
                                    }

                                }

                            }
                        }
                    }
                }

            //this is the case where a TRUE value is NOT found, LIKE is OFF (first time user vote)
            } else if object?.count == 0 {

                //add row to table
                let addUserVote = PFObject(className: "UserVotes")

                addUserVote["song"] = self.songs[row]
                addUserVote["username"] = PFUser.currentUser()?.username
                addUserVote["vote"] = true

                addUserVote.saveInBackgroundWithBlock {
                    (success: Bool, error: NSError?) -> Void in

                    if (success) {

                        if let error = error {
                            if let errorString = error.userInfo["error"] as? String {

                                self.displayAlert("Error", message: errorString)

                            }


                        } else {

                            let query = PFQuery(className:"PlaylistData")
                            query.whereKey("song", equalTo: self.songs[row])

                            query.findObjectsInBackgroundWithBlock { (object: [PFObject]?, error: NSError?) -> Void in

                                if error == nil {

                                    if let object = object! as? [PFObject] {

                                        for object in object {

                                            var voteCount:Int = object["numVotes"] as! Int
                                            voteCount = voteCount + 1
                                            object["numVotes"] = voteCount
                                            object.saveInBackground()
                                        }

                                    }

                                }
                            }

                        }


                    } else {

                        // There was a problem, check error.description

                    }
                }



            }

        } else {
            // Log details of the failure
            print("Error: \(error!) \(error!.userInfo)")
        }

    }

}

//If the LIKE button is ON perform this. This means that a record in the database has been found with a value of TRUE.
func voteButtonTurnOffFromCellRow(var row: Int) {

    // At this point, the value needs to be changed to FALSE, and the vote count needs to be decreased by 1.

    //note: does not take into account scenario where there are duplicate records (slight case)
    let query = PFQuery(className:"UserVotes")
    query.whereKey("username", equalTo: (PFUser.currentUser()?.username)!)
    query.whereKey("song", equalTo: songs[row])
    query.whereKey("vote", equalTo: true)

    query.findObjectsInBackgroundWithBlock { (object: [PFObject]?, error: NSError?) -> Void in

        if error == nil {

            if let object = object! as? [PFObject] {

                for object in object {

                    object["vote"] = false
                    object.saveInBackground()

                    let query = PFQuery(className:"PlaylistData")
                    query.whereKey("song", equalTo: self.songs[row])

                    query.findObjectsInBackgroundWithBlock { (object: [PFObject]?, error: NSError?) -> Void in

                        if error == nil {

                            if let object = object! as? [PFObject] {

                                for object in object {

                                    var voteCount:Int = object["numVotes"] as! Int
                                    voteCount = voteCount - 1
                                    object["numVotes"] = voteCount
                                    object.saveInBackground()
                                }

                            }

                        }
                    }

                }

            } else {

                print(error)
            }
        }

    }

}

}

最佳答案

在按钮操作中,将按钮 userInteractionEnabled 属性在方法的开头切换为 NO,在方法结束时切换为 YES。这可能对你有帮助

关于ios - SWIFT:快速点击 UIButton 会导致选票计数不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33668980/

相关文章:

objective-c - 无法在 Swift 中使用 class_copyPropertyList 获取可选变量

Swift 3 var 弃用错误

swift - 添加将对象添加到 PFUser

ios - 在标签栏 Controller 上使用导航栏

ios - 使用 MapKit 时 Xcode 7.3 不会自动完成

ios - 将 GraphicsServices 私有(private)框架添加到 IOS

ios - 编码更新,我是否将供应配置文件改回?

ios - 加速框架中的 vfp.h 在 XCode 4.0.2 上没有链接

ios - 中断 UITableView 单元格调整大小动画?

ios - Swift - 如何实现 "like post"