I tried using the main thread to show but it didn't work, any thought why the alert doesn't show up right away?
@IBAction func updateData(_ sender: Any) {
let alert = UIAlertController(title: "Updating data", message: "Please wait...", preferredStyle: .alert)
alert.view.tintColor = UIColor.black
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 10,y: 5,width: 50, height: 50)) as UIActivityIndicatorView
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
DispatchQueue.main.async {
self.present(alert, animated: true)
}
UIAlertController can not be customized, so for me the best solution was to create a custom UIView XIB and then instatiate it on the ViewController I need.
The XIB View could be like this:

then you create a CustomAlertLoadingView.swift file which subclass UIView, associate it to the XIB and create the IBOutlets.
To show it in any ViewController just create this extension
extension UIViewController {
func presentAlert(title: String) {
let nib = UINib(nibName: "CustomAlertLoadingView", bundle: nil)
let customAlert = nib.instantiate(withOwner: self, options: nil).first as! CustomAlertLoadingView
customAlert.tag = 12345
customAlert.titleAlertLabel.text = title
customAlert.indicator.startAnimating()
let screen = UIScreen.main.bounds
customAlert.center = CGPoint(x: screen.midX, y: screen.midY)
self.view.addSubview(customAlert)
}
}
use self.yourViewController.presentAlert(title:"yourTitle")
To dismiss the alert, create this function inside the UIVIewController extension
func dismissCustomAlert() {
if let view = self.view.viewWithTag(12345) {
view.removeFromSuperview()
}
}
then call self.yourViewController.dismissCustomAlert
I ran this through Xcode without any delay:
@IBAction func updateData(_ sender: UIButton) {
print("button fire")
let alert = UIAlertController(title: "Updating data", message: "Please wait...", preferredStyle: .alert)
alert.view.tintColor = UIColor.black
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 10,y: 5,width: 50, height: 50)) as UIActivityIndicatorView
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
self.present(alert, animated: true)
}
I replaced the sender parameter of your function with a UIButton and took out the Dispatch call to the main queue since it's unnecessary. No delays at all!
When you say that there is a delay do you mean only when you step trough the code? Because yes if you're stepping through it, the alert view won't be displayed right after self.present(alert, animated: true). You'll have to wait until the function completes execution. But that "delay" isn't visible to the human eye. Did you trying running the above code without stepping through it?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With