简体   繁体   English

如何更改UITableViewRowAction的标题

[英]How to change the title for UITableViewRowAction

I have a use case where I need to change the title of the UITableViewRowAction . 我有一个用例,我需要更改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. 例如,我有一个餐厅单元格,当向右滑动时,我显示“书签(104)”,其中“书签”是动作,104表示已有104人为其添加书签。 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. 单击它时,我希望它更改为“书签(105)”,因为显然有一个新用户(当前用户自己)已经为其添加了书签。 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 . 初始化一堆Restaurant对象,并将它们放在一个名为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. 然而,我对Andrew Carter试图通过子视图直接访问编辑动作中的UIButton感到好奇。 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: 首先,创建对UITableViewCell (或单元格数组)的引用,您希望修改,对于此示例,我将使用单个单元格:

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). 我们正在寻找UITableViewCellDeleteConfirmationView_UITableViewCellActionButton对象(链接的私有头文件以供参考)。

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. 此答案使用私有API建议在App Store上使用。 Apparently there is no way to change the title of the native UITableViewRowAction . 显然,无法更改本机UITableViewRowActiontitle 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. 在这里,我将遍历UITableViewCell的子视图,其中包含私有子视图,并且可能会发生变化,因此如果Apple更改视图层次结构,您的代码可能会在未来的iOS版本上崩溃。 I found the header of UIButtonLabel here . 我在这里找到了UIButtonLabel的标题。

The current view hierarchy as per iOS 9.2 is iOS 9.2的当前视图层次结构是

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]
} 

@JAL is totally right- you need to make your own sliding view to accomplish this, or be ok with reloading the cell and having it updated on the next slide out. @JAL是完全正确的 - 您需要创建自己的滑动视图来完成此任务,或者可以重新加载单元格并在下一张幻灯片中更新它。 Just for fun I tried to hack my way through the subviews and find the label and was able to find it, but what's funny is Apple has somehow blocked any changes being made to the text of that label. 只是为了好玩,我试图通过子视图破解我的方式并找到标签并且能够找到它,但有趣的是Apple以某种方式阻止了对该标签文本的任何更改。 You can change it's background color / other properties but not the text! 您可以更改它的背景颜色/其他属性,但不能更改文本!

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
        return cell
    }

    func findRowActionLabelForCell(cell: UITableViewCell?) -> UILabel? {
        guard let cell = cell else {
            return nil
        }
        var label: UILabel? = nil

        for view in cell.subviews {
            label = findRowActionLabelForView(view)
            if label != nil {
                break
            }
        }

        return label
    }

    func findRowActionLabelForView(view: UIView) -> UILabel? {
        for subview in view.subviews {
            if let label = subview as? UILabel {
                return label
            } else {
                return findRowActionLabelForView(subview)
            }
        }

        return nil
    }

    func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
        let action = UITableViewRowAction(style: .Default, title: "Test", handler: { (action, indexPath) -> Void in

            let cell = self.tableView.cellForRowAtIndexPath(indexPath)
            if let label = self.findRowActionLabelForCell(cell) {
                label.text = "New Value"
                label.backgroundColor = UIColor.blueColor()
            }

        })

        return [action]
    }

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

    }

}

之前 后

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM