iosswiftasynchronousuialertcontroller

Dismissal of UIAlertController inside async function


i am struggeling with a issue as following:

i start some network processing inside a async function:

func upload(
    object: object, 
    context: NSManagedObjectContext
) async -> Dictionary<String,String> {

}

therefor to inform the user that a time consuming process has just been started i display a alert controller:

let alert = UIAlertController(
    title: "Loading", 
    message: "Please wait...", 
    preferredStyle: .alert
)
self.present(alert, animated: true, completion: nil)

at the end of that function if everything worked out as planed i do dismiss that alert controller successfully, and show another alert:

alert.dismiss(
    animated: true, 
    completion: {
        let messageAlert = UIAlertController(
            title: "Success", 
            message: "Upload complete", 
            preferredStyle: .alert
        )
        messageAlert.addAction(
            UIAlertAction(
                title: "OK", 
                style: .default, 
                handler: { (action: UIAlertAction) in
                    //
                }
            )
        )
        self.present(
            messageAlert, animated: true, completion: nil
        )
    }
)

but i also want to dismiss that alert and show a new one when an error occured, but the first alert controller never gets dismissed:

guard dataString.replacingOccurrences(
    of: "\n", 
    with: ""
) != "no valid userID" else {
    error = true
    alert.dismiss(
        animated: true, 
        completion: {
            let messageAlert = UIAlertController(
                title: "Warning", 
                message: "no valid userID received",
                preferredStyle: .alert
            )
            messageAlert.addAction(
                UIAlertAction(
                    title: "OK", 
                    style: .default, 
                    handler: { (action: UIAlertAction) in
                        //
                    }
                )
            )
            self.present(
                messageAlert, 
                animated: true, 
                completion: nil
            )
        }
    )
    returnDic = [
        "result": "error",
        "info": "no valid userID received"
    ]
    return returnDic
}

i just can't wrap my head around why i am able to close it at the end of that function but not somewhere down the road.. Xcode is also complaining about not being able to present a new alert if one is actually being displayed right now..

[Presentation] Attempt to present <UIAlertController: 0x15880a200> on 
    <Project.ContainerViewController: 0x153708290> (
    from <Project.LockerViewController: 0x155018200>) 
    while a presentation is in progress.

i already tried to work with an observer like:

var error = Bool() {
    didSet {
        alert.dismiss(animated: true)
    }
}

it gets called, but the view does not get dismissed again :/

any ideas?


Solution

  • i've found a solution: The problem was that the presenting of that alert controller has not finished yet, and so it could not be dismissed at that time.

    a fix for this is f.e.:

    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                        alert.dismiss(animated: true)
    }
    

    i've realized this with attaching a closure block to

    self.present(alert,animated: true) { print("alert controller is visible") }
    

    and at the time of dimissal that text has not been printed out yet ;)

    i hope this is usefull for somebody else as well ;)