<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 Dec 3, 2015, at 2:15 PM, Douglas Gregor <<a href="mailto:dgregor@apple.com" class="">dgregor@apple.com</a>> wrote:</div><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 Dec 3, 2015, at 12:32 PM, Dan Stenmark <<a href="mailto:daniel.j.stenmark@gmail.com" class="">daniel.j.stenmark@gmail.com</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="">There’s a some of debate in the community regarding best practice for asynchronous completion callbacks. These practices include:<div class=""><br class=""></div><div class="">- Single Block w/ Mutually Exclusive Result and Error Objects (the current standard convention in Cocoa, though originally designed with Objective-C in mind)</div><div class="">- Double Block (one for success, one for failure)</div><div class="">- Swift Enum w/ Associated Objects (as described here: <a href="http://www.developerdave.co.uk/2015/09/better-completion-handlers-in-swift/" class="">http://www.developerdave.co.uk/2015/09/better-completion-handlers-in-swift/</a>)</div><div class=""><br class=""></div><div class="">Even prior to Swift, Apple’s code guidelines never explicitly addressed this topic. Going forward into the brave new world of Swift, are there going to be new preferred API design guidelines for this?</div></div></div></blockquote><br class=""></div><div class="">This is a great point, and there are a number of other issues related to callbacks/closure arguments that would benefit from guidelines. For example, I've seen the “Double Block” case where the second block ends up being a trailing closure, which makes for non-intuitive uses.</div></div></div></blockquote><br class=""></div><div><div>Hi Dan!</div><div><br class=""></div><div>I think guidelines in this area would be great.<br class=""></div><div><br class=""></div><div>Here are the tradeoffs I think we have for each approach:</div><div><br class=""></div><div><div class="">1) The single block approach means you’d code against an optional result and an optional error, making it easy to write invalid code (see example in #2). With the single block you can use trailing closure syntax coherently. I think most ObjC APIs use this approach since it works well in ObjC.<br class=""><br class=""></div><div class="">2) As Doug mentioned, the double block can be inconvenient / awkward but it does produce more correct code. </div><div class=""><b class=""><br class=""></b></div><div class=""><b class="">Doug</b>: maybe we can limit using trailing closures from being used if the 2nd to last parameter is also a closure? That would eliminate some confusion at the call site.</div><div class=""><br class=""></div><div class="">Some ObjC APIs use this approach. One positive aspect of the double-block approach is that it always produces code that’s less indented than the single block approach. e.g.</div><div class=""><br class=""></div><div class=""> /*</div><div class=""> Single block.</div><div class=""> Trailing closure syntax works well.</div><div class=""> */</div><div class=""> request.fetch { result, error in</div><div class=""> // More indented code since we need to use guard or if let.</div><div class=""> guard let result = result else {</div><div class=""> // Need to force unwrap `error`.</div><div class=""> handleFetchError(error!) </div><div class=""> return </div><div class=""> }</div><div class=""><br class=""></div><div class=""> use(result)</div><div class=""> }</div><div class=""><br class=""></div><div class=""> /*</div><div class=""> Double block.</div><div class=""> Trailing closure syntax is awkward here.</div><div class=""> */</div><div class=""> request.fetch(withCompletionHandler: { result in</div><div class=""> use(result) </div><div class=""> }, errorHandler: { error in</div><div class=""> // Don’t need to force unwrap `error`.</div><div class=""> handleFetchError(error) </div><div class=""> })</div><div class=""><br class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">3) Enums with associated values are conceptually nice, but unless we have a Result<> or an Either<> in the Standard Library I think most people will write one-off enums for each set of methods that return a specific kind of result + error. That adds an unnecessary conceptual burden since you need to know the type of of the value that’s passed to each callback. Also, we don’t have any primarily ObjC APIs that use this approach yet. It would also suffer from the same indentation problem as #1 but without the “invalid code” problem. If we go this route I think we’d want to map the async error ObjC APIs to use this approach similar to what we do with non-async error handling.</div><div class=""><br class=""></div><div class="">Looking at the tradeoffs I think I prefer #2 if we could limit the ability to use a trailing closure for the last parameter. I’d want to look at more code with the change though. We should also consider whether we should map the single block APIs in ObjC into double block APIs. What do you think?</div><div class=""><br class=""></div><div class="">Also, with any of these approaches there’s also the question of whether we pass ErrorType, NSError, or the specific error type.</div></div></div></div></div><div><br class=""></div><div>- Alex</div><div class=""><br class=""></div></div><br class=""></body></html>