可重复使用的表格视图单元格中的 UIButton 图像切换问题
Posted
技术标签:
【中文标题】可重复使用的表格视图单元格中的 UIButton 图像切换问题【英文标题】:UIButton image toggling issue in reusable tableview cell 【发布时间】:2016-02-24 18:41:31 【问题描述】:我正在尝试在我的社交网络 ios 应用程序中实现一个点赞功能 - 使用 Swift、Parse 作为后端和 Storyboard - 用户可以在其中喜欢(和不喜欢)类似于 Instagram 或 Facebook iOS 应用程序的帖子。
唯一的问题似乎是,当用户滚动帖子的 tableview 提要时,当前用户不喜欢的其他帖子显示填充的喜欢按钮图像(好像他们被喜欢,但他们不是) .
根据我的研究,我了解到这可能是因为 tableview 中的单元格是可重复使用的(通过 tableView.dequeueReusableCellWithIdentifier
.)* 这是有道理的,因为当用户打开应用程序时,只有可见的单元格被加载.并且当用户滚动 tableview 时,单元格会被回收。
因此,我进行了更多研究,发现尝试解决此问题的一种方法是使用prepareForReuse()
方法重置自定义单元格的likeButton IBOutlet 图像。 tableView:cellForRowAtIndexPath: 中的 table view 的委托然后在重用单元格时重置所有内容,包括 likeButton 图像以及基于从 like 查询获得的结果的一些逻辑。它最初可以工作,但不幸的是,当用户尝试点赞帖子时,由于某种原因,这会破坏点赞按钮的行为。
更新:这里不需要 prepareForResuse() 作为答案的建议之一。
// In custom cell file:
override func prepareForReuse()
super.prepareForReuse()
// Set likeButton image to the default unfilled version
let image = UIImage(named: "likeButtonUnfilled")
self.likeButton.setImage(image, forState: UIControlState.Normal)
在 post feed viewcontroller 文件的cellForRowAtIndexPath
中:
// currUserLikeObjects is an array of PFObjects that contains the results returned from the like query (all of the objects that the current user has liked)
for object in currUserLikeObjects
if object["toPost"]?.objectId! == postObject.objectId
// Toggle likeButton image to filled version
let image = UIImage(named: "likeButtonFilled") as UIImage!
cell.likeButton.setImage(image, forState: UIControlState.Normal)
在likeButtonTapped
post feed viewcontroller 文件中:
func likeButtonTapped(sender: UIButton)
sender.enabled = false
let indexPath = NSIndexPath(forRow: sender.tag, inSection: 0)
let cell = tableView.cellForRowAtIndexPath(indexPath) as! PostTableViewCell
let likeObject = PFObject(className: ParseHelper.ParseLikeClass)
var likedPost: PFObject = (self.objects![indexPath.row] as? PFObject)!
if (cell.likeButton.currentImage!.isEqual(UIImage(named: "likeButtonUnfilled")))
/* The post is NOT liked already by the currentUser (likeButton image is NOT filled)
1. Save the like object to Parse
2. If successfully saved, increment the likeCount and update it in Parse (Remember: Enable likeButton)
3. If successfully saved, toggle the image to the filled version
*/
// 1
likeObject["fromUser"] = PFUser.currentUser()!
likeObject["toPost"] = likedPost
likeObject.saveInBackgroundWithBlock (success: Bool, error: NSError?) -> Void in
if (error == nil)
print("SUCCESS: Saved likeObject in database.")
// 2
likedPost.incrementKey(ParseHelper.ParsePostLikeCount, byAmount: 1)
likedPost.saveInBackgroundWithBlock (success: Bool, error: NSError?) -> Void in
if (error == nil)
// The likeCount key has been incremented
print("SUCCESS: The likeCount key has been incremented. Toggling like button image to FILLED.")
// 3
var image = UIImage(named: Helper.likeButtonFilled)
cell.likeButton.setImage(image, forState: UIControlState.Normal)
else
// There was a problem, check error.description
print("FAIL: The likeCount key has NOT been incremented.")
// Delete the likeObject since the likeCount was not successfully saved
likeObject.deleteInBackgroundWithBlock( (succeeded: Bool?, error: NSError?) -> Void in
if (error == nil)
print("SUCCESS: Deleted likeObject from Parse since likeCount key has not successfully been incremented.")
self.showAlertMessage((error?.description)!)
else
print("FAIL: Unable to delete the likeObject from Parse in response to likeCount key NOT incrementing.")
)
print("Enabling sender & reloading data.")
sender.enabled = true
self.tableView.reloadData()
else
print("FAIL: Unable to save like object in Parse.")
self.showAlertMessage("Unable to like this post at this time.")
else if (cell.likeButton.currentImage!.isEqual(UIImage(named: "likeButtonFilled")))
/* The post is liked already by the currentUser (likeButton image is filled)
1. Delete the likeObject from Parse
2. If successfully deleted, only if the likeCount is greater than 0 to avoid a negative likeCount, decrement the likeCount and update it in Parse (Remember: Enable likeButton)
3. If successfully deleted, toggle the image to the unfilled version
*/
// 1
likeObject.deleteInBackgroundWithBlock( (succeeded: Bool?, error: NSError?) -> Void in
if (error == nil)
print("SUCCESS: Deleted likeObject from Parse (unliked post).")
// 2
likedPost.incrementKey(ParseHelper.ParsePostLikeCount, byAmount: -1)
likedPost.saveInBackgroundWithBlock (success: Bool, error: NSError?) -> Void in
if (error == nil)
// The likeCount key has been decremented
print("SUCCESS: The likeCount key has been decremented.")
// 3
var image = UIImage(named: Helper.likeButtonUnfilled)
cell.likeButton.setImage(image, forState: UIControlState.Normal)
else
print("FAIL: The likeCount key has NOT been decremented.")
// Delete the likeObject from the Like class since the likeCount was not successfully saved?
print("Enabling sender & reloading data.")
sender.enabled = true
self.tableView.reloadData()
else
print("FAIL: Unable to delete the like object from Parse.")
)
【问题讨论】:
【参考方案1】:在您的情况下不需要使用prepareForReuse
方法,您可以通过以下方式替换cellForRowAtIndexPath
中的代码来实现:
// Set likeButton image to the default unfilled version
var image = UIImage(named: "likeButtonUnfilled")
// currUserLikeObjects is an array of PFObjects that contains the results returned from the like query (all of the objects that the current user has liked)
for object in currUserLikeObjects
if object["toPost"]?.objectId! == postObject.objectId
// Toggle likeButton image to filled version
image = UIImage(named: "likeButtonFilled") as UIImage!
break // Terminate loop when we found required object
self.likeButton.setImage(image, forState: UIControlState.Normal)
要使上述代码正常工作,还需要您在完成 Like/Unlike 操作时相应地更新 currUserLikeObjects
并更新特定的 tableview 单元格以反映屏幕上的修改。
【讨论】:
谢谢。我尝试了您的代码并对其进行了测试:我喜欢一个帖子,点赞按钮图像切换到填充版本。 当我拉动刷新或向下滚动然后返回到点赞的帖子时,点赞帖子的点赞按钮图像会切换回未填充的版本。 但如果我退出应用然后再次打开它,点赞按钮我喜欢的帖子的图像已正确设置为填充版本。注意:在 currUserLikeObjects 中存储like 对象的likeQuery 在viewDidLoad
中调用。
@dnadri 正如我在回答中解释的那样,当您对任何帖子进行服务器查询并获得成功时,您还需要更新您的 currUserLikeObjects (通过使用 objectId 向其中添加新对象,您会得到作为响应),对于不同(通过删除与 objectId 匹配的对象形式数组)相同
是的,我在likeButtonTapped
func 中有代码,当用户点击like 按钮时在 Parse 中添加一个新的like 对象,并在用户不喜欢时删除该新的like 对象,这反过来应该更新currUserLikeObjects
.
我更新了我的问题以显示我的 likeButtonTapped func 代码,该代码在用户喜欢/不喜欢时添加/删除对象,正如你所说。为了使这项工作正常工作,我还缺少什么?以上是关于可重复使用的表格视图单元格中的 UIButton 图像切换问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在 cellforrowatindexpath 之后更新自定义表格单元格中的 UIButton 图像?
iOS:表格单元格中的 UILabel 和 UIButton