[swift-evolution] [Proposal] Make optional protocol methods first class citizens

Dietmar Planitzer dplanitzer at q.com
Fri Apr 1 20:50:03 CDT 2016


That’s an interesting idea. Although I still do not like the fact that the Swift model forces me to split up the implementation between the delegating type and the delegate whereas the ObjC model allows me to keep the default and non-default implementation in a single place, namely the type.

There are some additional questions that I think have not received a satisfactory answer yet:

a) the ObjC model makes it straight forward to ADD new functionality to a delegate without breaking existing apps. Eg the tableView(heightForRowAtIndexPath:) method was added in Mac OS X 10.4. Before that the NSTableView did not support variable row heights. The only change to the API that Apple had to introduce in order to allow apps to create tables with variable row heights was this one optional delegate method. App implements it -> table view stores a per-row height; app does not implement it -> table view uses a fixed row height which is set as a property on the table. And so existing apps would continue to run with the new AppKit version just fine.

How would this work in the Swift model?


b) the ObjC model allows for significant and in some cases important optimizations:

b1) NSTableView support fixed and variable row heights. Layout can be much simpler for fixed row heights and there is no need to store the per-row height in an internal cache. In the ObjC model the table view has an efficient means to detect whether the delegate wants fixed or variable row heights since all it needs to do is check whether the tableView(heightForRowAtIndexPath:) is implemented. If it is -> call it for every row and cache the row height and enable the variable row height layout code; otherwise -> do not cache per row heights and enable the fixed row height layout code. Note that the code that does the actual heavy duty work (the layout code) may be far remove from the code that calls the tableView(heightForRowAtIndexPath:) method. In the Swift model though, we would have to invoke the tableView(heightForRowAtIndexPath:) for every row and compare the return results before we could even decide if the delegate wants variable or fixed row heights.

b2) the ObjC model allows me to get the implementation of the optional delegate method which in turn allows me to completely remove dynamic dispatch from the performance critical path.

How would these things work in the Swift model?


Regards,

Dietmar Planitzer


> On Apr 1, 2016, at 18:20, Rob Mayoff via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
>         class UITableView {
>                 ...
>                 private func addRow(at indexPath: NSIndexPath) {
>                         ...
>                         cell.size.height = delegate?.tableView(self, heightForRowAtIndexPath: indexPath) ?? rowHeight
>                         ...
>                 }
>                 ...
> 
> You need not duplicate the default logic:
> 
> private class DefaultDelegate: NSObject, UITableViewDelegate { }
> private let defaultDelegate = DefaultDelegate()
> 
> public class UITableView {
> 
>     private func addRow(at indexPath: NSIndexPath) {
>         ...
>         cell.size.height = (delegate ?? defaultDelegate).tableView(self, heightForRowAtIndexPath: indexPath)
>         ...
>     }
> 
> }
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list