Take this UITableViewController
subclass:
final class MyTableViewController: UITableViewController {
override func tableView(_ tableView: UITableView,
willDisplay cell: UITableViewCell,
forRowAt indexPath: IndexPath) {
super.tableView(tableView, willDisplay: cell, forRowAt: indexPath)
}
The above code crashes with the well known unrecognized error message, because the parent class didn't implement the method. The UITableViewDataSource
method in discussion is optional, and it makes sense for UITableViewController
not to have implemented it.
However, I think we have a compiler issue here: the method is not exposed as optional when attempting to call it via super
, so there's one compile-time check that we miss. This might be caused by the fact that only protocols have support for optional methods, so I think this is a corner-case of Swift.
Also, being forced to write override
, even if the parent class doesn't implement the method, can lead to confusion, since developers might expect for the base parent to already have it implemented.
In order to avoid runtime crashes, the developer needs to be diligent and add respondsTo
checks:
if super.responds(to: #selector(tableView(_:willDisplay:forRowAt:))) {
super.tableView(tableView, willDisplay: cell, forRowAt: indexPath)
}
, however this adds more boilerplate, and it's a runtime check only.
Also, the documentation for UITableViewController
is not very helpful in respect to this, as it doesn't mention which methods from the datasource/delegate protocols are implemented, so one can easily fall into this trap of calling super
on a non-existing method.
Is this worth fixing within the compiler? Or should Apple just update the documentation for UITableViewController
(and other classes that exhibit similar behaviour, like the collection view controller) to reflect this quirk?