I have a use case where I need to change the title of the UITableViewRowAction
. For example, I have a restaurant cell, and when swipe right I show "bookmark(104)" where "bookmark" is the action and 104 means there have been 104 people bookmarked it. When click on it, I want it to change to "bookmark(105)" because obviously there's a new user(the current user himself) has bookmarked it. How do I do that? Tried the below code and it doesn't work.
let likeAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "bookmark\n\(count)", handler:{(action, indexpath) -> Void in
....
count++
action.title = "bookmark\n\(count)"
});
Here's a quick and dirty example.
Say you have a class Restaurant with a name and likes value:
class Restaurant {
var name: String?
var likes: Int = 0
}
You initialize a bunch of Restaurant
objects, and put them in an array called dataSource
. Your table view data source methods will look like this:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataSource.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .Default, reuseIdentifier: "cell");
cell.textLabel?.text = dataSource[indexPath.row].name
return cell
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
// This can be empty if you're not deleting any rows from the table with your edit actions
}
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
// First, create a share action with the number of likes
let shareAction = UITableViewRowAction(style: .Default, title: "\(self.dataSource[indexPath.row].likes)") { (action, indexPath) -> Void in
// In your closure, increment the number of likes for the restaurant, and slide the cell back over
self.dataSource[indexPath.row].likes++
self.tableView.setEditing(false, animated: true)
}
return [shareAction] // return your array of edit actions for your cell. In this case, we're only returning one action per row.
}
I'm not going to write a scrollable cell from scratch, since this question has a bunch of options you can use.
I was, however, intrigued by Andrew Carter's attempt to iterate through subviews to access the UIButton
in the edit action directly. Here is my attempt:
First, create a reference to the UITableViewCell
(or an array of cells), you wish to modify, for this example, I'll be using a single cell:
var cellRef: UITableViewCell?
// ...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .Default, reuseIdentifier: "cell");
cell.textLabel?.text = dataSource[indexPath.row].name
cellRef = cell;
return cell
}
In your share action, iterate through the button's subviews. We're looking for the UITableViewCellDeleteConfirmationView
and _UITableViewCellActionButton
objects (private headers linked for reference).
let shareAction = UITableViewRowAction(style: .Default, title: "\(self.dataSource[indexPath.row].likes)") { (action, indexPath) -> Void in
var deleteConfirmationView: UIView? // UITableViewCellDeleteConfirmationView
if let subviews = self.cellRef?.subviews {
for subview in subviews {
if NSClassFromString("UITableViewCellDeleteConfirmationView") != nil {
if subview.isKindOfClass(NSClassFromString("UITableViewCellDeleteConfirmationView")!) {
deleteConfirmationView = subview
break
}
}
}
}
if let unwrappedDeleteView = deleteConfirmationView {
if unwrappedDeleteView.respondsToSelector("_actionButtons") {
let actionbuttons = unwrappedDeleteView.valueForKey("_actionButtons") as? [AnyObject]
if let actionButton = actionbuttons?.first as? UIButton { // _UITableViewCellActionButton
actionButton.setTitle("newText", forState: .Normal)
}
}
}
}
This answer uses private API and it's NOT recommended to be used on the App Store. Apparently there is no way to change the title
of the native UITableViewRowAction
. You may have to implement your custom solution as suggested by others to achieve the result you want.
Here I'm traversing the subviews of UITableViewCell
which contains private subviews and are subject to change so your code may crash on future iOS releases if Apple changes the view hierarchy.
I found the header of UIButtonLabel
here.
The current view hierarchy as per iOS 9.2 is
UITableViewCell
UITableViewCellDeleteConfirmationView
_UITableViewCellActionButton
UIButtonLabel
UIButton
Here is the code:
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let shareAction = UITableViewRowAction(style: .Default, title: "\(dataList[indexPath.row].likes)") { (action, indexPath) -> Void in
self.dataList[indexPath.row].likes++
let cell = tableView.cellForRowAtIndexPath(indexPath)
let privateView = cell!.subviews[0].subviews[0].subviews[0]
let privateButton = privateView.valueForKey("_button") as! UIButton
privateButton.setTitle("\(self.dataList[indexPath.row].likes)", forState: .Normal)
}
return [shareAction]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With