Simplify Your UIAlertController Creation with @resultBuilder in Swift
Ever wished you could make your UIAlertController
setup cleaner and more intuitive? Enter @resultBuilder
, a powerful feature in Swift that can help you create domain-specific languages (DSLs) within Swift, making your code more readable and maintainable.
In this article, i will explore how to use @resultBuilder
to streamline the creation of UIAlertController
. This is reallife case, when i use in my applications.
By the end of this guide, you'll be able to create alert controllers with multiple actions in a more modular and organized way.
What is @resultBuilder?
@resultBuilder
(formerly known as @functionBuilder
) is an attribute in Swift that enables you to create DSLs. It allows you to build complex structures using a clean and declarative syntax, similar to SwiftUI.
Let’s dive into an example where we use @resultBuilder
to simplify the creation of UIAlertController
:
Step 1: Define the Structure for UIAlertAction
First, i will create a structure to represent an alert action:
import UIKit
struct AlertAction {
let title: String
let style: UIAlertAction.Style
let handler: ((UIAlertAction) -> Void)?
}
Step 2: Define the @resultBuilder
Next, i will define our @resultBuilder
, which will aggregate alert actions into an array:
@resultBuilder
struct AlertBuilder {
static func buildBlock(_ components: AlertAction...) -> [AlertAction] {
return components
}
}
Step 3: Extend UIAlertController to Use @resultBuilder
I then extend UIAlertController
to accept our @AlertBuilder
:
extension UIAlertController {
convenience init(
title: String?, message: String?,
preferredStyle: UIAlertController.Style,
@AlertBuilder actions: () -> [AlertAction]
) {
self.init(title: title, message: message, preferredStyle: preferredStyle)
let builtActions = actions()
for action in builtActions {
let alertAction = UIAlertAction(title: action.title, style: action.style, handler: action.handler)
self.addAction(alertAction)
}
}
}
Step 4: Create a Helper Function for AlertAction
To make it easier to create AlertAction
objects, we'll define a helper function:
func AlertAction(
title: String,
style: UIAlertAction.Style = .default,
handler: ((UIAlertAction) -> Void)? = nil
) -> AlertAction {
return AlertAction(title: title, style: style, handler: handler)
}
Step 5: Use the DSL to Create a UIAlertController
Finally, we use our DSL to create a UIAlertController
:
func showAlert(on viewController: UIViewController) {
let alert = UIAlertController(title: "Title", message: "Message", preferredStyle: .alert) {
AlertAction(title: "OK") { _ in
print("OK tapped")
}
AlertAction(title: "Cancel", style: .cancel) { _ in
print("Cancel tapped")
}
AlertAction(title: "Destructive", style: .destructive) { _ in
print("Destructive tapped")
}
}
viewController.present(alert, animated: true, completion: nil)
}
Explanation
- AlertAction: A structure representing an alert action, containing the title, style, and handler.
- AlertBuilder: A
@resultBuilder
that aggregates actions into an array. - UIAlertController Extension: Adds a convenient initializer that takes
@AlertBuilder
and creates actions based on the provided data. - AlertAction Function: Simplifies the creation of
AlertAction
objects. - Using the DSL: Creates a
UIAlertController
using the new DSL syntax, adding actions in a cleaner and more intuitive way.
Conclusion
This example demonstrates how @resultBuilder
can be utilized to create a DSL that simplifies the creation process of UIAlertController
with multiple actions. This approach makes the code more readable and easier to maintain, especially when you need to add several actions to an alert.
By leveraging @resultBuilder
, you can make your UIAlertController setup more modular and organized, improving both development speed and code quality.
Try it out in your next project and see how much cleaner and more maintainable your code can be!