Erik Erik - 10 days ago 7
iOS Question

Building animations into a subclass of UITableView

I've created a table view that I really like - it plays some nice animations in the delegate function

tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
.

The trouble is, I can't find a way to duplicate that behavior elsewhere in my codebase without copy and pasting the code inside the delegate function and violating DRY. I want to be able to adjust the animation parameters of all the tableviews in my project from one place.


  1. First I tried to write a subclass of
    UITableView
    , but that's no good because the animations are specified in a delegate function. You could make the subclass its own delegate and define the behavior you want, but then none of its other delegate functions are available to its containing view.

  2. I considered writing a protocol that inherits from
    UITableViewDelegate
    , but then you would have to reimplement every tableview delegate function in the protocol even though only one of them is different.

  3. I thought about trying to swizzle the willDisplayCell function, but I'm not sure that would work, and I really don't want to mess with swizzling if I stay away from it.



How can I pull something like this off? Both in this very specific case, and in the more general OOP sense of wanting to provide default behavior for a delegate function without having to set the class as its own delegate?

Edit: It's not something that you can really take a picture of, but nonetheless screenshot as requested.
enter image description here

Answer

You should not subclass UITableView, nor swizzle, or extend the delegate protocol.

What I would do is to write a class that implements and wraps the delegate methods. This class could have it's own delegate, but I'd rather give it closures to call.

class TableViewDelegate: UITableViewDeleagte {
    var willDisplayCell: ((UITableView, UITableViewCell, IndexPath) -> Void)?
    let animator: Animator
    weak var tableView: UITableView? {
        didSet {
            tableView?.delegate = self
        }
    }
    init(tableView: UITableView, animator: Animator) {
        self.animator = animator
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UItableViewCell, forRowAt indexPath: IndexPath ) {
        animator.animate(cell)
        willDisplayCell?(tableView, cell, indexPath)
    }
}
Comments