【问题标题】:Patterns for Showing a Toast Popup with Custom UITableViewCell使用自定义 UITableViewCell 显示 Toast 弹出窗口的模式
【发布时间】:2017-01-20 16:43:00
【问题描述】:

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

self.tableView.addGestureRecognizer(cell.longPress)

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

这个表格视图单元格的代码如下:

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()
}

【问题讨论】:

    标签: ios swift design-patterns swift3 cocoa-design-patterns


    【解决方案1】:

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

    • 让 TableViewController 负责:
      • 创建吐司(仅一次)
      • 配置 toast
      • 显示吐司
      • 响应长按手势
      • 配置表格视图单元格
    • 只允许 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 中配置您的单元格并将 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(with title: String) 像:

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

    【讨论】:

    • 这太完美了。我已经开始在委托方向上工作,并且您的编辑包括 CustomTableViewCell 上的新选择器将其置于顶部。感谢您的帮助!
    • @dstepan 很高兴我能帮上忙。
    猜你喜欢
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-16
    相关资源
    最近更新 更多