avatarAntoine van der lee 🇳🇱

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

1475

Abstract

          <div>
            
            <iframe class="gist-iframe" src="/gist/BetterProgramming/f7b737fbc24f657c4ec8ec3694f4e271.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><p id="eea5">The <code>buttonTapped(_:)</code> method will be called every time the button is tapped.</p><p id="066d">The same piece of code can now be written as follows:</p>
    <figure id="aff7">
        <div>
          <div>
            
            <iframe class="gist-iframe" src="/gist/BetterProgramming/c9453ef1813269d9c10e2c283505592f.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><p id="2793">This keeps the action close to the control definition, which can improve the discoverability of your code.</p><h2 id="648f">Getting a reference to the control sender</h2><p id="0c58">One difference in the piece of code above is that our method had a reference to the sender. This could be handy in some cases when you want to know which of the controls in place called the linked method.</p><p id="0a08">With the new closure-based API, you can use the <code>action</code> argument to access the sender. For example, when you want to read out the text from a text field:</p><div id="ec9f"><pre><span class="hljs-keyword">let</sp

Options

an> textField <span class="hljs-operator">=</span> <span class="hljs-type">UITextField</span>() textField.addAction(<span class="hljs-type">UIAction</span>(title: <span class="hljs-string">""</span>, handler: { action <span class="hljs-keyword">in</span> <span class="hljs-keyword">let</span> textField <span class="hljs-operator">=</span> action.sender <span class="hljs-keyword">as!</span> <span class="hljs-type">UITextField</span> <span class="hljs-built_in">print</span>(<span class="hljs-string">"Text is <span class="hljs-subst">(textField.text)</span>"</span>) }), for: .editingChanged)</pre></div><h1 id="967f">Should I Always Use the New Closure API?</h1><p id="af5e">It might be tempting to now use closures everywhere. However, a control action can easily grow in code, making your code less readable. In those cases, you might want to fall back to the old target-action pattern that allows you to use a separate method.</p><p id="8335">Methods in Swift are easier to read when your control action requires multiple lines of code.</p><h1 id="3b90">Conclusion</h1><p id="bbda">The new closure-based API in the iOS 14 SDK is a welcome change, but it should be used carefully. Using many closures can easily make your code less readable and should only be used if the control callback logic can be written in a few lines of code. Otherwise, it’s better to use the old-fashioned target-action pattern.</p><p id="a30b">Thanks for reading!</p></article></body>

Adding a Closure as a Target to a UIButton and Other Controls in Swift

This oft-requested API has finally arrived

Photo by engin akyurt on Unsplash.

The target-action pattern is used in combination with user interface controls as a callback to a user event. Whenever a button is pressed on a target, its action will be called. The fact that the method is not defined close to the control definition is sometimes seen as a downside and reason for a lot of us developers to search for closure-based solutions on sites like Stack Overflow.

The iOS 14 SDK introduced new APIs that allow us to use UIControls in combination with closures. Common UIControl elements are UIButton, UISegmentedControl, and UISwitch, but there are a lot more that all inherit from the UIControl object. All those interface elements can now be used with this new API.

Using a UIControl With a Closure Callback

You’re most likely familiar with the following piece of code:

The buttonTapped(_:) method will be called every time the button is tapped.

The same piece of code can now be written as follows:

This keeps the action close to the control definition, which can improve the discoverability of your code.

Getting a reference to the control sender

One difference in the piece of code above is that our method had a reference to the sender. This could be handy in some cases when you want to know which of the controls in place called the linked method.

With the new closure-based API, you can use the action argument to access the sender. For example, when you want to read out the text from a text field:

let textField = UITextField()
textField.addAction(UIAction(title: "", handler: { action in
    let textField = action.sender as! UITextField
    print("Text is \(textField.text)")
}), for: .editingChanged)

Should I Always Use the New Closure API?

It might be tempting to now use closures everywhere. However, a control action can easily grow in code, making your code less readable. In those cases, you might want to fall back to the old target-action pattern that allows you to use a separate method.

Methods in Swift are easier to read when your control action requires multiple lines of code.

Conclusion

The new closure-based API in the iOS 14 SDK is a welcome change, but it should be used carefully. Using many closures can easily make your code less readable and should only be used if the control callback logic can be written in a few lines of code. Otherwise, it’s better to use the old-fashioned target-action pattern.

Thanks for reading!

Programming
Swift
Swift Programming
iOS
Mobile Development
Recommended from ReadMedium