Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialAaron Watkins
10,902 PointsImplementing a Like Button in a TableView using Parse.com/Swift
Hi everyone,
I'm working on a social app and trying to implement the customary "like button" for posts by users. Each post is in its own custom tableViewCell (a PFTableViewCell). I'm trying to follow the Anypic tutorial in the parse.com documentation, but I'm getting stuck at a few parts. One part in particular is updating the like counter. Here is what happens (so far) when a user taps the like button:
// MARK: - Like button
func like(sender:UIButton) {
var senderButton = sender
//I tried to access the cell this way, but build fails: let cell = tableView.cellForRowAtIndexPath(senderButton.tag)
var postLike:PFObject = (objects as NSArray).objectAtIndex(senderButton.tag) as PFObject
//disable like button so user cannot duplicate request
shouldEnableLikeButton(enable:false)
setLikeStatus(liked:true)
var liked = !senderButton.selected
//get current number of likes on post
if var likeCounter = postLike["likeCount"] as? Int {
//let cell = tableView.cellForRowAtIndexPath(senderButton.tag)
//update likeCount
if liked {
likeCounter = likeCounter + 1
println(likeCounter)
cell.label_likes.text = "\(likeCounter)" //build fails here because I'm unable to access the custom cell
}else {
likeCounter = likeCounter - 1
println(likeCounter)
cell.label_likes.text = "\(likeCounter)" //build fails here because I'm unable to access the custom cell
}
}
Has anybody else been able to implement a like button and wouldn't mind sharing their approach. It is greatly appreciated. I've been stuck for a while on this one. :-(
4 Answers
Stone Preston
42,016 PointsAaron Watkins I think I solved your problem. you need to create an NSIndexPath from the row (which is stored in the button tag), since cellForRowAtIndexPath takes an index path. currently you are just passing it a row, which is an int:
let indexPath = NSIndexPath(forRow: sender.tag, inSection: 0)
let cell = tableView.cellForRowAtIndexPath(indexPath)
that should make it work. let me know if it doesnt
Aaron Watkins
10,902 PointsStone Preston - absolutely right. That was exactly it. My mistake was assuming that i could use indexPath and sender interchangeably since I was just looking to identify the cell by the row number. Thank you and Stephen Whitfield very much! really appreciate you guys.
Stone Preston
42,016 Pointsno problem. glad I could help
dnadri
3,758 PointsStone Preston I am trying to use your approach for implementing a like/unlike button functionality in my social app and am experiencing an issue - I can better explain privately. Any way I can reach you to show you the problem?
Stone Preston
42,016 Pointsthis button.tag trick is pretty common. the button.tag is going to be set in cellForRowAtIndex path. basically what you do is inside that method, you set the buttons tag to the indexPath.row variable, that way each button corresponds to a specific index path.
you also need to attach the button to a function that gets called when you press it
so make sure you have something like this in your cellForRow method:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// ...
cell.likeButton.tag = indexPath.row
cell.likeButton.addTarget(self, action: "like:", forControlEvents: UIControlEvents.TouchUpInside)
// ...
}
Stephen Whitfield
16,771 PointsHaven't looked at the problem you're having in particular, but one comment I can make off the bat is setting the instance of your cell to the current indexPath and not the sender's tag. A suggestion too is not to set you sender to a local variable, since you've already defined that the sender is of type UIButton in your method params.
Aaron Watkins
10,902 PointsThanks a lot guys
Stone Preston - I'm able to pass the indexPath to this function via the bit of code you had above. I had that in my cellForRow method. Based on what Stephen Whitfield said, I'll definitely not assign my sender to a local variable...now that I think about it, that is unnecessary.
But here's the tricky thing I'm running into. Each custom cell has a like button and a label. The like button executes the function which SHOULD increment/decrement the value in the label (the like count). When I print to the console, I'm able to increment the like count for each cell, but I can't figure out how to update the label. If it were in the cellForRow method I would do something like:
cell.label_likes.text = "\(likeCounter)" //where likeCounter is the updated value of like counts after the like button is pressed.
But I can't access that label.
Stone Preston
42,016 Pointsah I see. and when you say it fails when you try and use cellForRowAtIndexPath, what do you mean fails? does it crash?
Stephen Whitfield
16,771 PointsMaybe you could create a separate method that updates the label when the button is pressed?
let likeButton = UIButton(frame: devSetFrame)
likeButton.addTarget(self, action: "syncUI:", forControlEvents: .TouchUpInside)
func syncUI(sender: UIButton) {
//Update cell label here
}
Stone Preston
42,016 Pointsstill the same problem. he needs access to the cell where the button is that was pressed. using cellForRowAtIndexPath is what he needs, but for some reason its not working
Stephen Whitfield
16,771 PointsAh! Ok. He needs to access the cell outside of the cellForRow method. I've done this before in the past by creating a property of type CustomCell. No idea if it's preferred, but it works. I instantiated the cell in the cellForRow method so that the current cell is available in other parts of my code. Maybe you could try that and see if it works.
Aaron Watkins
10,902 PointsStone Preston - sorry I shouldn't have said "failed". It doesn't compile when I try to run it.
Stephen Whitfield - would you mind providing a sample of your recommendation? I'll give it a shot.
Thanks again, guys. really appreciate your help. I've been staring at this thing for a while.
Stone Preston
42,016 Pointswhat build errors do you get when you try and run it with that method call in there
Lukes Ivi
2,001 PointsLukes Ivi
2,001 PointsHey, do you mind sending the repository for this? I'm having a similar issue but I'm unable to replicate it through the code in this discussion.