iOS Custom Button with Label

Implementing a custom button featuring a label, using Swift5 and UIKit 🕹
Creating our button class
We start by creating a new file, ButtonWithLabel
. To keep our button customizable, we initialize our class with a type and an action.
<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIKit</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">class</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">ButtonWithLabel</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIView </span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">typealias</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">Action</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> (() </span><span style="color: var(--shiki-token-keyword)">-></span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">Void</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-keyword)">?</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">var</span><span style="color: var(--shiki-color-text)"> action: (() </span><span style="color: var(--shiki-token-keyword)">-></span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">Void</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-keyword)">?</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">enum</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">ButtonWithLabelType</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">case</span><span style="color: var(--shiki-color-text)"> info</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">case</span><span style="color: var(--shiki-color-text)"> alert</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">var</span><span style="color: var(--shiki-color-text)"> type: ButtonWithLabelType</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">init</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-function)">type</span><span style="color: var(--shiki-color-text)">: ButtonWithLabelType) {</span></span>
<span><span style="color: var(--shiki-color-text)"> self.type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> type</span></span>
<span><span style="color: var(--shiki-color-text)"> super.</span><span style="color: var(--shiki-token-keyword)">init</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">frame</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .null</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">required</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">init?</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-function)">coder</span><span style="color: var(--shiki-color-text)">: NSCoder) {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">fatalError</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-string-expression)">"init(coder:) has not been implemented"</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">@discardableResult</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">func</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">with</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-function)">action</span><span style="color: var(--shiki-color-text)">: Action) </span><span style="color: var(--shiki-token-keyword)">-></span><span style="color: var(--shiki-color-text)"> Self {</span></span>
<span><span style="color: var(--shiki-color-text)"> self.action </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> action</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> self</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">@objc</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">func</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">click</span><span style="color: var(--shiki-color-text)">() {</span></span>
<span><span style="color: var(--shiki-color-text)"> action</span><span style="color: var(--shiki-token-keyword)">?</span><span style="color: var(--shiki-color-text)">()</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span></span>
Creating the label and the icon
Because we want the entire class to be pressable, we create both our label and our button as UIButton
elements, and we add the previously created click
function as the buttons click-targets. I've also added some simple styling to the label button, giving it some padding and a background color. We will style the button in the next step.
<span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">lazy</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">var</span><span style="color: var(--shiki-color-text)"> label: UIButton </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">let</span><span style="color: var(--shiki-color-text)"> button </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIButton</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span><span style="color: var(--shiki-color-text)"> button.contentEdgeInsets </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIEdgeInsets</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">top</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-constant)">6</span><span style="color: var(--shiki-token-function)">, left</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-constant)">6</span><span style="color: var(--shiki-token-function)">, bottom</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-constant)">6</span><span style="color: var(--shiki-token-function)">, right</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-constant)">6</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> button.backgroundColor </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> .white.</span><span style="color: var(--shiki-token-function)">withAlphaComponent</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-constant)">0.8</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> button.</span><span style="color: var(--shiki-token-function)">addTarget</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">self, action</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> #selector</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">click</span><span style="color: var(--shiki-token-punctuation)">)</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .touchUpInside</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> button</span></span>
<span><span style="color: var(--shiki-color-text)">}</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">lazy</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">var</span><span style="color: var(--shiki-color-text)"> icon: UIButton </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">let</span><span style="color: var(--shiki-color-text)"> button </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIButton</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span><span style="color: var(--shiki-color-text)"> button.</span><span style="color: var(--shiki-token-function)">addTarget</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">self, action</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> #selector</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">click</span><span style="color: var(--shiki-token-punctuation)">)</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .touchUpInside</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> button</span></span>
<span><span style="color: var(--shiki-color-text)">}</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span></span>
Setting the label text and styling the icon
We want to create our label text and choose our icon based on the provided ButtonWithLabelType
. To do this, we create a helper function, updateStyling()
. In this example, I've used icons from SF Symbols.
<span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">func</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">updateStyling</span><span style="color: var(--shiki-color-text)">() {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">switch</span><span style="color: var(--shiki-color-text)"> type {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">case</span><span style="color: var(--shiki-color-text)"> .info</span><span style="color: var(--shiki-token-keyword)">:</span></span>
<span><span style="color: var(--shiki-color-text)"> label.</span><span style="color: var(--shiki-token-function)">setTitle</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-string-expression)">"Info"</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .normal</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> icon.</span><span style="color: var(--shiki-token-function)">setImage</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">UIImage</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">systemName</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-string-expression)">"questionmark.circle"</span><span style="color: var(--shiki-token-punctuation)">)</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .normal</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">case</span><span style="color: var(--shiki-color-text)"> .alert</span><span style="color: var(--shiki-token-keyword)">:</span></span>
<span><span style="color: var(--shiki-color-text)"> label.</span><span style="color: var(--shiki-token-function)">setTitle</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-string-expression)">"Alert"</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .normal</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> icon.</span><span style="color: var(--shiki-token-function)">setImage</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">UIImage</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">systemName</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-string-expression)">"exclamationmark.circle"</span><span style="color: var(--shiki-token-punctuation)">)</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .normal</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Positioning
We update our init
function to call the newly created updateStyling
. We also place our label and our icon in a UIStackView
.
<span><span style="color: var(--shiki-token-keyword)">init</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-function)">type</span><span style="color: var(--shiki-color-text)">: ButtonWithLabelType) {</span></span>
<span><span style="color: var(--shiki-color-text)"> self.type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> type</span></span>
<span><span style="color: var(--shiki-color-text)"> super.</span><span style="color: var(--shiki-token-keyword)">init</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">frame</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .null</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">updateStyling</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">let</span><span style="color: var(--shiki-color-text)"> stack </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIStackView</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">arrangedSubviews</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> [label, icon]</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> stack.</span><span style="color: var(--shiki-token-constant)">alignment</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> .center</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">addSubview</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">stack</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> stack.</span><span style="color: var(--shiki-token-function)">fillInSuperview</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Usage
We can now start using our new button by setting a type and giving it an action. In this example, I use it as a rightBarButtonItem.
<span><span style="color: var(--shiki-token-keyword)">let</span><span style="color: var(--shiki-color-text)"> infoButton </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">ButtonWithLabel</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">type</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .info</span><span style="color: var(--shiki-token-punctuation)">)</span><span style="color: var(--shiki-color-text)">.</span><span style="color: var(--shiki-token-function)">with</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">action</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> showInfoView</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)">navigationItem.rightBarButtonItem </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIBarButtonItem</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">customView</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> infoButton</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span></span>
And that's it! Here is the completed class:
<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIKit</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">class</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">ButtonWithLabel</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIView </span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">typealias</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">Action</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> (() </span><span style="color: var(--shiki-token-keyword)">-></span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">Void</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-keyword)">?</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">var</span><span style="color: var(--shiki-color-text)"> action: (() </span><span style="color: var(--shiki-token-keyword)">-></span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">Void</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-keyword)">?</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">enum</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">ButtonWithLabelType</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">case</span><span style="color: var(--shiki-color-text)"> info</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">case</span><span style="color: var(--shiki-color-text)"> alert</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">var</span><span style="color: var(--shiki-color-text)"> type: ButtonWithLabelType</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">lazy</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">var</span><span style="color: var(--shiki-color-text)"> label: UIButton </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">let</span><span style="color: var(--shiki-color-text)"> button </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIButton</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span><span style="color: var(--shiki-color-text)"> button.contentEdgeInsets </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIEdgeInsets</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">top</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-constant)">6</span><span style="color: var(--shiki-token-function)">, left</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-constant)">6</span><span style="color: var(--shiki-token-function)">, bottom</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-constant)">6</span><span style="color: var(--shiki-token-function)">, right</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-constant)">6</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> button.backgroundColor </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> .white.</span><span style="color: var(--shiki-token-function)">withAlphaComponent</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-constant)">0.8</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> button.</span><span style="color: var(--shiki-token-function)">addTarget</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">self, action</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> #selector</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">click</span><span style="color: var(--shiki-token-punctuation)">)</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .touchUpInside</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> button</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">lazy</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">var</span><span style="color: var(--shiki-color-text)"> icon: UIButton </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">let</span><span style="color: var(--shiki-color-text)"> button </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIButton</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span><span style="color: var(--shiki-color-text)"> button.</span><span style="color: var(--shiki-token-function)">addTarget</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">self, action</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> #selector</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">click</span><span style="color: var(--shiki-token-punctuation)">)</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .touchUpInside</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> button</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">init</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-function)">type</span><span style="color: var(--shiki-color-text)">: ButtonWithLabelType) {</span></span>
<span><span style="color: var(--shiki-color-text)"> self.type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> type</span></span>
<span><span style="color: var(--shiki-color-text)"> super.</span><span style="color: var(--shiki-token-keyword)">init</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">frame</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .null</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">updateStyling</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">let</span><span style="color: var(--shiki-color-text)"> stack </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UIStackView</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">arrangedSubviews</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> [label, icon]</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> stack.</span><span style="color: var(--shiki-token-constant)">alignment</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> .center</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">addSubview</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">stack</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> stack.</span><span style="color: var(--shiki-token-function)">fillInSuperview</span><span style="color: var(--shiki-token-punctuation)">()</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">required</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">init?</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-function)">coder</span><span style="color: var(--shiki-color-text)">: NSCoder) {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">fatalError</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-string-expression)">"init(coder:) has not been implemented"</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">func</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">updateStyling</span><span style="color: var(--shiki-color-text)">() {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">switch</span><span style="color: var(--shiki-color-text)"> type {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">case</span><span style="color: var(--shiki-color-text)"> .info</span><span style="color: var(--shiki-token-keyword)">:</span></span>
<span><span style="color: var(--shiki-color-text)"> label.</span><span style="color: var(--shiki-token-function)">setTitle</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-string-expression)">"Info"</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .normal</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> icon.</span><span style="color: var(--shiki-token-function)">setImage</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">UIImage</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">systemName</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-string-expression)">"questionmark.circle"</span><span style="color: var(--shiki-token-punctuation)">)</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .normal</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">case</span><span style="color: var(--shiki-color-text)"> .alert</span><span style="color: var(--shiki-token-keyword)">:</span></span>
<span><span style="color: var(--shiki-color-text)"> label.</span><span style="color: var(--shiki-token-function)">setTitle</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-string-expression)">"Alert"</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .normal</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> icon.</span><span style="color: var(--shiki-token-function)">setImage</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">UIImage</span><span style="color: var(--shiki-token-punctuation)">(</span><span style="color: var(--shiki-token-function)">systemName</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> </span><span style="color: var(--shiki-token-string-expression)">"exclamationmark.circle"</span><span style="color: var(--shiki-token-punctuation)">)</span><span style="color: var(--shiki-token-function)">, for</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-token-function)"> .normal</span><span style="color: var(--shiki-token-punctuation)">)</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">@discardableResult</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">func</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">with</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-function)">action</span><span style="color: var(--shiki-color-text)">: Action) </span><span style="color: var(--shiki-token-keyword)">-></span><span style="color: var(--shiki-color-text)"> Self {</span></span>
<span><span style="color: var(--shiki-color-text)"> self.action </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> action</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> self</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">@objc</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">private</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">func</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">click</span><span style="color: var(--shiki-color-text)">() {</span></span>
<span><span style="color: var(--shiki-color-text)"> action</span><span style="color: var(--shiki-token-keyword)">?</span><span style="color: var(--shiki-color-text)">()</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>