{"id":9,"date":"2018-11-05T19:28:42","date_gmt":"2018-11-05T19:28:42","guid":{"rendered":"https:\/\/benkau.com\/2018\/11\/05\/2018-11-5-responder-controller\/"},"modified":"2021-02-21T18:23:49","modified_gmt":"2021-02-21T18:23:49","slug":"responder-controller","status":"publish","type":"post","link":"https:\/\/benkau.com\/responder-controller\/","title":{"rendered":"Responder Chain Controller"},"content":{"rendered":"\n<p>While reading the <a href=\"https:\/\/iosdevweekly.com\/search?q=next\" target=\"_blank\" rel=\"noopener\">iOSDevWeekly<\/a> recently, I came across a great post from <a href=\"https:\/\/rolandleth.com\/\" target=\"_blank\" rel=\"noopener\">Roland Leth<\/a> entitled \u2018<a href=\"https:\/\/rolandleth.com\/handling-the-next-button-automatically\" target=\"_blank\" rel=\"noopener\">Handling the Next Button<\/a>\u2019. Although a great approach, I had recently implemented a very different automated solution and thought it might be worth sharing.<\/p>\n\n\n\n<p>In this post, I\u2019m going to cover an implementation that makes use of a <code>ResponderController<\/code> for navigating our user interfaces.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"background\">Background<\/h1>\n\n\n\n<p>In most of our apps handling the <code>Next<\/code> button is often an exercise is patience. It can be troublesome if left unconsidered and although a totally solvable problem, finding a nice reusable abstraction can prove difficult.<\/p>\n\n\n\n<p>I\u2019ve recently been working on an app for <a href=\"http:\/\/thread.com\" target=\"_blank\" rel=\"noopener\">Thread<\/a> and we had a need for <code>Next<\/code>\/<code>Previous<\/code> buttons during checkout, sign-in and various other screens. The architecture means that most of our UI is made up of reusable \u2018components\u2019 \u2013 which unfortunately meant that any 2 text fields likely didn\u2019t know about each other, nor which context they are being presented in.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"architecture\">Architecture<\/h1>\n\n\n\n<p>When I built <a href=\"http:\/\/gitHub.com\/shaps80\/Peek\" target=\"_blank\" rel=\"noopener\">Peek<\/a> \u2013 I was driven by the idea that functionality and features could be composed on top of the existing user interface. so the approach I\u2019m going to cover leans on these same practices.<\/p>\n\n\n\n<p>What if we just scanned the interface automatically and found all the <code>UIResponder<\/code>\u2019s we care about and provide a simple API for navigating them?<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"respondercontroller\">ResponderController<\/h1>\n\n\n\n<p>I\u2019m not going to cover the code in detail since I have provided a Playground and a link to a <a href=\"https:\/\/gist.github.com\/shaps80\/c17ddb6596bc138e44037c820242553d\" target=\"_blank\" rel=\"noopener\">Gist<\/a> for those that want to see how it works and try it out themselves.<\/p>\n\n\n\n<p>Basically the controller just takes a view (allowing you to use multiple controllers for sub-forms) which is then \u2018scans\u2019 for <code>UIResponder<\/code> subclasses that you might care about.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p style=\"white-space: pre-wrap;\">It filters out those that are hidden, disabled, etc\u2026<\/p><\/blockquote>\n\n\n\n<p>It then provides API\u2019s for accessing <code>previous<\/code>, <code>next<\/code>, <code>current<\/code>, <code>begin<\/code> &amp; <code>resign<\/code>.<\/p>\n\n\n\n<p>Where ResponderController really shines though is that it also exposes Objective-C compatible interfaces via <code>IBOutlet<\/code> and <code>IBAction<\/code> which allows you to even design your \u201cNext Button\u201d navigation without a single line of code.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p style=\"white-space: pre-wrap;\">To see the Interface Builder approach in action, download the Xcode project below.<\/p><\/blockquote>\n\n\n\n<p>The <code>IBAction<\/code> APIs even allow you to hook up things like buttons on a toolbar:<\/p>\n\n\n\n<pre class=\"wp-block-code swift\"><code>UIBarButtonItem(title: \"Next\", style: .plain, \n    target: responder, action: #selector(ResponderController.next(_:))<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"summary\">Summary<\/h1>\n\n\n\n<p>This doesn\u2019t solve all problems, but we found this approach to be much closer to a plug-and-play solution than others we\u2019d implemented before.<\/p>\n\n\n\n<p>If you liked this approach or have another approach, look me up on Twitter or leave a comment below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p class=\"post-excerpt\">A zero-code-required, plug-in approach to \u2018Next\u2019 button handling in iOS, including Interface Builder support.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[91],"class_list":["post-9","post","type-post","status-publish","format-standard","hentry","category-swift","tag-uikit"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/posts\/9","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/comments?post=9"}],"version-history":[{"count":3,"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/posts\/9\/revisions"}],"predecessor-version":[{"id":325,"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/posts\/9\/revisions\/325"}],"wp:attachment":[{"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/media?parent=9"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/categories?post=9"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/benkau.com\/wp-json\/wp\/v2\/tags?post=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}