Alerts
manages displaying UIAlertControllers in succession by coordinating them in a queue.
The main reason of creating this project was provide a fix for the following console log:
Warning: Attempt to present UIAlertController: on viewController: which is already presenting
when presenting multiple alerts. If are aware of this message then you understand the use case of coordinating alerts in your app. Especially in apps that heavily rely on alerts.
Swift 5.0+ Xcode 14 iOS 11.0+
The project is built on three objects: Alert
, AlertAction
and AlertCoordinator
.
Alerts are managed by an AlertCoordinator
singleton (AlertCoordinator.main
) which holds three queues based on priority. The queues follow a First In First Out (FIFO) sequence. The coordinator queues up alerts based on priority automatically, can be paused, and told when to display alerts. The coordinator manages three queues internally for high, default and low alerts. The higher priority alerts are dequeued first followed by default then low.
Alert
is a wrapper class on UIAlertController
that adds functionality for priority. Apple strictly states to not subclass UIAlertController
for adding features so the class only holds a UIAlertController
class within and doesn't subclass it.
An Alert
class holds a priority for the coordinator to queue the alert correctly.
Higher priority alerts are presented first and can also present over lower priority alerts when added to the coordinator if it is actively displaying. If a high priority alert is on display already and another high is added then the waits for the current to be dismissed.
Medium priority is the default priority and acts like a normal alert. If a higher is priority is added the coordinator will dismiss a default priorty alert and it will be queued up again to be displayed after the higher queue is completed.
Low priority is for alerts that don't need much action and will be dismissed and discarded if another higher priority alert is queued.
AlertAction
is a wrapper class on UIAlertAction
that are actions for an Alert
. The AlertAction
will notify the AlertCoordinator
on completion automatically to allow other others to display. Long running actions can be performed on an AlertAction
that can keep other alerts from displaying until the task is complete. When the task is complete manually call the complete()
class method to notify the coordinator on the task completion.
let helloWorldAlert = Alert(title: "Hello", message: "World", alertActions: [.defaultAction()]) // .defaultAction() creates a default confirmation AlertAction with a title of Okay
AlertCoordinator.main.enqueue(alert: helloWorldAlert)
AlertCoordinator.main.display()
for i in 0...5 {
let alert = Alert(title: "\(i)", message: "", alertActions: [.defaultAction()])
AlertCoordinator.main.enqueue(alert: alert)
}
AlertCoordinator.main.display() // Alerts from 0 to 5 display in order
If you want to display an alert and hold the coordinator from displaying any other alerts until a task is completed.
let paymentAction = AlertAction(title: "Yes", style: .default, preferred: true, completeOnDismiss: false) { alert in
// present another view controller for payment and on it's dismissal call AlertAction.complete()
self.present(paymentVC, animated: true, completion: nil)
}
let alert = Alert(title: "Make a payment", message: "No", alertActions: [.defaultAction()])
alert.actions = [.defaultAction(), paymentAction]
AlertCoordinator.main.enqueue(alert: alert)
AlertCoordinator.main.display()
/// In PaymentViewController.swift
/// completes payment
func completePayment {
dismiss(animated: true) {
AlertAction.complete() // Alert Coordinator will begin to display any pending alerts in queue
}
}
let high = Alert(title: "High", message: "Message", priority: .high, alertActions: nil)
let medium = Alert(title: "Default", message: "Message", priority: .medium, alertActions: nil)
let low = Alert(title: "Low", message: "Message", priority: .low, alertActions: nil)
Copy over the AlertCoordinator.swift
file from the Alert
folder in the project to your project.
Joshua Alvarado - Twitter
This project is released under the MIT license.