Nearly every project/app needs an alert popup. It is an essential UI element to:
- Provide information/warning to the user before performing any action
- Handle user interaction to perform any action
- Notify the user on completion of an action
The default alert popup is very simplistic. Nowadays, we see a unique style and attractive UI in popups rather than showing a classic native/default one.
What do you show in a popup?
Title, message, image, and action buttons. Isn't it? But if you want to make your custom alert popup, it requires a lot of effort as you need to manage
- UI design
- Constraints
- Action handler
- Device orientation
- Animation and many more
Due to these reasons, creating your popup is a very challenging task. A third-party library also has its limitations.
While I was investigating a better way to put in place a custom native alert. My goal was to customize the native alert view (UIAlertController
). I found, by setting UIViewController
as the content view of the UIAlertController
, I can achieve it.
This would save a lot of time and effort.
Let's see how to integrate UIViewController
as a custom view of UIAlertController
.
I am going to add UIViewController
inside the storyboard and configure it with the class. I will also add an image view and two labels inside UIViewController
to show the title and message with the image in the popup as following image and code. messageLabel
will be used to calculate the preferredContentSize
of UIViewController
. You can add details and modify UI.
@IBOutlet private weak var imageView: UIImageView!
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var messageLabel: UILabel!
var alertImage = UIImage()
var titleText = String()
var messageText = String()
override func viewDidLoad() {
super.viewDidLoad()
setValues()
// Do any additional setup after loading the view.
}
private func setValues() {
imageView.image = alertImage
titleLabel.text = titleText
messageLabel.text = messageText
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
preferredContentSize.height = messageLabel.frame.size.height + messageLabel.frame.origin.y + 30
}
Once the view controller's configuration completes, I will add a method to set the above view controller as a content view of a UIAlertController.
I will also add the init
method for initialization and addAlertAction
method to handle actions as follows:
extension UIAlertController {
convenience init(style: UIAlertController.Style, title: String? = nil, message: String? = nil) {
self.init(title: title, message: message, preferredStyle: style)
}
func addAlertAction(title: String, style: UIAlertAction.Style = .default, handler: ((UIAlertAction) -> Void)? = nil) {
let action = UIAlertAction(title: title, style: style, handler: handler)
addAction(action)
}
func setViewController(image: UIImage, title: String, message: String) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let viewController =
storyboard.instantiateViewController(withIdentifier: "CustomViewController") as? CustomViewController else {
return
}
viewController.alertImage = image
viewController.titleText = title
viewController.messageText = message
setValue(viewController, forKey: "contentViewController")
}
}
That's it. The alert popup is ready. Now you only need to call alert popup method.
private func showAlertController() {
let alertView = UIAlertController(style: .alert)
alertView.setViewController(image: #imageLiteral(resourceName: "alert"), title: "Alert", message: "Message Content")
alertView.addAlertAction(title: "Cancel") { (_) in
}
alertView.addAlertAction(title: "OK") { (_) in
}
present(alertView, animated: true, completion: nil)
}
You can also use custom view/XIB as the content view of UIAlertController
and update constraints.
You can download sample code from here.
I hope this blog helped you. If you have used any other library or solution, we would like to hear back from you. Please share it with your peers.
Thank you!