<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Nov 16, 2016, at 3:52 PM, Karl via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 16 Nov 2016, at 05:25, Shawn Erickson <<a href="mailto:shawnce@gmail.com" class="">shawnce@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="white-space:pre-wrap" class="">Again my point isn't worrying about point of calling out to the delegate but configuring my delegator to avoid a body of work or state management that is unneeded if the delegate doesn't care about some mix of potential delegation points. I was trying to point out things to consider for those stating "why not just provide a default implementation that is a nop, etc." when in fact knowing if the delegate decided to not implement something can be helpful for some delegators. <br class=""><br class="">Anyway as stated earlier sub protocols likely are good enough however I am concerned about it degenerating into a single func per sub protocol in not atypical situations.<br class=""><br class="">-Shawn </div><br class=""></div></blockquote><div class=""><br class=""></div></div>Even if it does just become a single method, it’s not a cause for concern. In the example before, we gave some semantic meaning to those bundles of optional methods, so that’s a bit of a win. Also, what’s cool is that instead of the members being optional, the conformance to the sub-protocol is what is optional, and anything which declares conformance must implement all of the extra callbacks. The upshot of this is that the compiler is able to validate everything and produce an error if the extra callbacks change in the future.<div class=""><br class=""></div><div class="">For example:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">class MyViewController : ScrollObserver { </font></div><div class=""><font face="Menlo" class=""> func scrollViewDidScroll(_ scrollview: UIScrollView) {</font></div><div class=""><font face="Menlo" class=""> // handle scroll</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">Now we decide to change the function signature of this optional callback (for some reason. Let’s say we want to add a parameter…):</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">protocol ScrollObserver : ScrollViewDelegate {</font></div><div class=""><font face="Menlo" class=""> func scrollViewDidScroll(_ scrollview: UIScrollView, <b class="">from lastLocation: CGPoint</b>)</font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">If the <i class="">method</i> was “optional”, objects would suddenly stop implementing this requirement and it would still be perfectly valid code. However, as a sub-protocol, we get proper validation and the compiler will produce an error until we update everything to handle the new signature.</div></div></div></blockquote><div><br class=""></div><div>We have the very same issue here with default implementations on protocols which is one of the reasons I've always supported the notion of somehow marking methods/vars that are supposed to implement a protocol, so that you get a warning/error when the protocol changes...</div><div><br class=""></div><div>Example:</div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><div><br class=""></div></div><div><div><span style="font-family: Menlo;" class="">p</span><span style="font-family: Menlo;" class="">rotocol ScrollObserver : ScrollViewDelegate {</span></div></div><div><div><span style="font-family: Menlo;" class=""> func scrollViewDidScroll(_ scrollview: UIScrollView</span><span style="font-family: Menlo;" class="">)</span></div></div><div><div><div class=""><font face="Menlo" class="">}</font></div></div></div><div><div><div class=""><font face="Menlo" class=""><br class=""></font></div></div></div><div><div><div class=""><font face="Menlo" class="">extension protocol </font><span style="font-family: Menlo;" class="">ScrollObserver {</span></div></div></div><div><div><div class=""><span style="font-family: Menlo;" class=""> func scrollViewDidScroll(_ scrollview: UIScrollView</span><span style="font-family: Menlo;" class="">) { </span></div></div></div><div><div><div class=""><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo;" class="">/* no-op */ </span></div></div></div><div><div><div class=""><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo;" class="">}</span></div></div></div><div><div><div class=""><span style="font-family: Menlo;" class="">}</span></div></div></div><div><div><br class=""></div></div><div><div><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><span style="font-family: Menlo;" class="">class MyViewController : ScrollObserver { </span></div></div></div><div><div><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><span style="font-family: Menlo;" class=""> func scrollViewDidScroll(_ scrollview: UIScrollView) {</span></div></div></div><div><div><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><span style="font-family: Menlo;" class=""> // handle scroll</span></div></div></div><div><div><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><span style="font-family: Menlo;" class=""> }</span></div></div></div><div><div><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><font face="Menlo" class="">}</font></div></div></div></div></blockquote><div><div><br class=""></div><div>Now the method declaration in the protocol changes to the suggested:</div><div><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><div><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><span style="font-family: Menlo;" class="">p</span><span style="font-family: Menlo;" class="">rotocol ScrollObserver : ScrollViewDelegate {</span></div></div></div><div><div><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><span style="font-family: Menlo;" class=""> func scrollViewDidScroll(_ scrollview: UIScrollView,</span><span style="font-family: Menlo;" class=""> </span><b class="" style="font-family: Menlo;">from lastLocation: CGPoint</b><span style="font-family: Menlo;" class="">)</span></div></div></div><div><div><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><font face="Menlo" class="">}</font></div></div></div></div></blockquote><div><br class=""></div><div>a) the declaration in the extension no longer provides the default implementation, yet the code compiles without a warning</div><div>b) when you fix the default implementation in the protocol extension, MyViewController still conforms to ScrollObserver, yet the default implementation is invoked instead.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">I think this problem has actually come up with @obj-c protocols. Some signatures changed in Swift 3 due to API overlay improvements and some conformances silently failed to resolve, IIRC.</div><div class=""><br class=""></div><div class="">- Karl</div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>