如何以编程方式触发UITableViewCell editActions?

时间:2017-11-10 12:44:25

标签: ios uitableview swift4

我在tableviewcell上做了一些自定义编辑操作。当我滑动时它工作正常,但我想知道当我点击单元格时是否有任何方法可以触发这些操作。此外,我看到很多人只是回答类似的问题,

tableView.setEditing(true, animated: true)

虽然这不是我想要的解决方案。我希望在不按下其他按钮的情况下立即显示动作。

This is what I mean by editActions

1 个答案:

答案 0 :(得分:0)

简短的回答是 - 没有这样的方式。

但是,如果你真的需要这样的东西,你可以模仿这种行为,虽然它需要你自己更多的实现和状态处理。

这是一个快速且非常脏的解决方案,它会覆盖自定义单元格的touchesEnded方法。请记住在相关故事板的表视图中将Cell设置为单元格的动态原型,并将其重用标识符设置为identitifer

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, CellDelegate {

    @IBOutlet weak var tableView: UITableView?
    override func viewDidLoad() {
        super.viewDidLoad()
    }

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

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "identifier") as? Cell else {
            return UITableViewCell()
        }
        cell.textLabel?.text = "\(indexPath.row)"
        cell.indexPath = indexPath
        cell.delegate = self
        return cell
    }

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        return nil
    }

    func doAction(for cell: Cell) {
        let indexPath = cell.indexPath
        print("doing action for cell at: \(indexPath!.row)")
        // your implementation for action
        // maybe delete a cell or whatever?
        cell.hideFakeActions()

    }

}

protocol CellDelegate: class {
    func doAction(for cell: Cell)
}

class Cell: UITableViewCell {

    weak var delegate: CellDelegate?
    var indexPath: IndexPath!

    @IBOutlet weak var buttonAction1: UIButton?
    @IBOutlet weak var constraintButtonFakeActionWidth: NSLayoutConstraint?

    override func awakeFromNib() {
        self.constraintButtonFakeActionWidth?.constant = 0
    }
    override func touchesEnded(_ touches: Set<UITouch>,
                               with event: UIEvent?) {
        guard let point = touches.first?.location(in: self) else {
            return
        }
        if self.point(inside: point, with: event) {

            print("event is in cell number \(indexPath.row)")
            self.showFakeActions()

        }
    }

    func showFakeActions() {
        self.constraintButtonFakeActionWidth?.constant = 80
        UIView.animate(withDuration: 0.3) {
            self.layoutIfNeeded()
        }
    }

    func hideFakeActions() {
        self.constraintButtonFakeActionWidth?.constant = 0
        UIView.animate(withDuration: 0.3) {
            self.layoutIfNeeded()
        }
    }

    @IBAction func fakeAction() {
        delegate?.doAction(for: self)
    }
}

那它是如何运作的?每个单元格都是UIView,它继承自抽象UIResponder接口。您可以覆盖其方法,以代表分派给它们的事件自行执行操作。这是您覆盖touchesEnded的第一步。

查看界面构建器的屏幕截图 - 您必须连接约束。 enter image description here

我还实现了委托,它为单元格的所有编辑操作返回nil,因此它们不会干扰您的解决方法。

接下来,设置自定义委托以从单元格获取回调。我还将IndexPath附加到单元格,以便于管理dataSource中的数据,这是您必须实现的。

请记住,此代码缺少很多,例如prepareForReuse方法实现。此外,您可能希望在touchesEnded覆盖中执行其他检查,这将确保每次触摸不会多次触发此委托回调并防止多次触摸。此处也未实现在单元上禁用用户交互的逻辑。并且界面需要微调(就像文本在动画期间似乎被压扁了一样)。