使用自定义 UITableViewCell 显示 Toast 弹出窗口的模式

Patterns for Showing a Toast Popup with Custom UITableViewCell

目前,我有一个 CustomTableViewCell 在四五个不同的地方使用。自定义单元格有一个延迟加载的 UILongPressGestureRecognizer 属性,它作为手势识别器添加到父 VC 的 cellForRowAtIndexPath 中。

self.tableView.addGestureRecognizer(cell.longPress)

当用户启动长按时,我希望弹出 toast 通知以显示一些上下文信息,然后在几秒钟后消失。我已将其包含在 CustomTableViewCell 的代码中,但所有这些决定都开始 "smell." 是否有更智能、更合乎逻辑的方式来实施这些决定?

此 table 视图单元格具有以下代码:

weak var parentTableView: UITableView?

lazy var longPress: UILongPressGestureRecognizer = {

    let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPressSelector))

    longPress.minimumPressDuration = 0.5
    longPress.delegate = self

    return longPress

}()

func longPressSelector(_ longPress: UILongPressGestureRecognizer!) {

    if let tableView = self.parentTableView {

        let point = longPress.location(in: tableView)

        let indexPath = tableView.indexPathForRow(at: point)

        if ((indexPath! as NSIndexPath).section == 0 && longPress.state == .began) {


            // do some work

            // Show informational popup
            let toast = createToastNotification(withTitle: addedSong.name)

            Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (timer) -> Void in
                UIView.animate(withDuration: 1.0) { () -> Void in
                    toast.alpha = 0.0
                    toast = nil
                }
            }
        }
    }

}

func createToastNotification(withTitle title: String) -> UIView {

    if let tableView = self.parentTableView {
        let windowFrame = tableView.superview?.bounds

        let height:CGFloat = 145, width: CGFloat = 145

        let x = (windowFrame?.width)! / 2 - width / 2
        let y = (windowFrame?.height)! / 2 - height / 2

        let toast = EnsembleToastView.create()

        toast.frame = CGRect(x: x, y: y, width: width, height: height)
        toast.songLabel.text = title
        toast.layer.cornerRadius = 5

        tableView.superview?.addSubview(toast)

        return toast
    }

    return UIView()
}

我认为 TableView 知道如何显示 toast 更有意义,因此我会在您的 tableViewCell 中创建一个协议,因此我将采取以下步骤。

  • 让 TableViewController 负责:
    • 创建 toast(仅一次)
    • 正在配置 toast
    • 敬酒
    • 响应长按手势
    • 正在配置您的 table 视图单元格
  • 只允许 YourTableViewCell 委托

所以让我们先响应长按手势

protocol TableViewCellLongPressDelegate {
    func tableViewCellHadLongPress(_ cell: YourTableViewCell)
}

然后扩展您的 TableViewController 以符合您的新协议

extension YourTableViewController : TableViewCellLongPressDelegate {
    func tableViewCellHadLongPress(_ cell: YourTableViewCell){
         //configure toast based on which cell long pressed
         configureToastNotification(with title: cell.title){
         //show toast
    }
}

现在,在您的 TableViewController 中配置您的 table 视图单元格 配置您的单元格并将 TableViewController 指定为 longPressDelegate

let cell = YourTableViewCell.dequeue(from: self.tableView)!
//configure cell
cell.tableViewCellLongPressDelegate = self

这种方法很好,因为您可以将 createToastNotification() 方法移动到您的 TableViewController 并负责创建 toast(仅一次)

var toastNotification : UIView?
viewDidLoad(){
    //yatta yatta
    toastNotification = createToastNotification()
}

那你可以把createToastNotification改成

func createToastNotification() -> UIView? {

    let windowFrame = self.bounds

    let height:CGFloat = 145, width: CGFloat = 145

    let x = (windowFrame?.width)! / 2 - width / 2
    let y = (windowFrame?.height)! / 2 - height / 2

    let toast = EnsembleToastView.create()

    toast.frame = CGRect(x: x, y: y, width: width, height: height)
    toast.layer.cornerRadius = 5

   self.addSubview(toast)

    return toast
}

最后,对于 YourTableViewController,配置 toast,让我们创建一个 configureToastNotification(标题:字符串),例如:

func configureToastNotification(with title: String){
    if let toast = self.toastNotification {
        toast.songLabel.text = title
    }
}

最后,我们从 YourTableViewCell 中删除了很多责任,允许它只委托 :

protocol TableViewCellLongPressDelegate : class {
    func tableViewCellHadLongPress(_ cell: YourTableViewCell)
}

class YourTableViewCell : UITableViewCell {

    //initializers

    weak var longPressDelegate: TableViewCellLongPressDelegate?

    lazy var longPress: UILongPressGestureRecognizer = {

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPressHappened))

        longPress.minimumPressDuration = 0.5
        longPress.delegate = self

        return longPress

    }()

    func longPressHappened() {
        self.longPressDelegate?.tableViewCellHadLongPress(self)
    }
}