Warning: UIAlertController is already presenting

16,285

Solution 1

You need to change your code like this, present the second alertController on completion of dismiss. Also change your if condition with my one.

if presentedViewController == nil {
     self.presentViewController(alertController, animated: true, completion: nil)
} else{
      self.dismissViewControllerAnimated(false) { () -> Void in
           self.presentViewController(alertController, animated: true, completion: nil)
      }
}

Hope this will help you.

Solution 2

Try this

if let presented = self.presentedViewController {
     presented.removeFromParentViewController()
  }

if presentedViewController == nil {
     self.present(alert, animated: true, completion: nil)
  }

Solution 3

Try this:

   [self dismissViewControllerAnimated:YES completion:nil];
    UIAlertController *alertResync = [UIAlertController alertControllerWithTitle:@"Warning"
                                                                         message:@"Warning Warning"
                                                                  preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *softResyncButton = [UIAlertAction actionWithTitle:@"No, keep Some"
                                                               style:UIAlertActionStyleDefault
                                                             handler:^(UIAlertAction * _Nonnull action) {

                                                             }];

        UIAlertAction *hardResyncButton = [UIAlertAction actionWithTitle:@"Yes"
                                                                   style:UIAlertActionStyleDestructive
                                                                 handler:^(UIAlertAction * _Nonnull action) {
                                                                     [self testFunc];
                                                                 }];
        [alertResync addAction:softResyncButton];
        [alertResync addAction:hardResyncButton];
        [self presentViewController:alertResync animated:YES completion:nil];

Solution 4

You can present another UIAlertController or anything else you want from current presented UIAlertController. Create a helper func to get top visible viewcontroller then make a present call on that

func topVisibleViewController(viewController: UIViewController) -> UIViewController? {
    let viewController = viewController ?? UIApplication.shared.keyWindow?.rootViewController

    if let navigationController = viewController as? UINavigationController, !navigationController.viewControllers.isEmpty {
        return visibleViewController(navigationController.viewControllers.last)
    }
    else if let tabBarController = viewController as? UITabBarController,
        let selectedController = tabBarController.selectedViewController {
        return visibleViewController(selectedController)
    }
    else if let presentedController = viewController?.presentedViewController {
        return visibleViewController(presentedController)
    }

    return viewController
}
Share:
16,285
CatiaV5
Author by

CatiaV5

Updated on June 17, 2022

Comments

  • CatiaV5
    CatiaV5 almost 2 years

    I am a novice in swift and XCode so please forgive me the probably really messy code! When running my code I get the following warning: Warning: Attempt to present on which is already presenting

    I have already checked the forum and found a post regarding that issue....I applied the help suggested as in:

    if presentedViewController !== nil {
         self.presentViewController(alertController, animated: true, completion: nil)
    } else{
         self.dismissViewControllerAnimated(false, completion: nil)
         self.presentViewController(alertController, animated: true, completion: nil)
    }
    

    However, it still gives me the same warning....So I guess I must have done something wrong there. It would be great if someone could help me out please :) Also if there any suggestion as to how I can "clean" up my code are appreciated :)

    import UIKit
    
    class ViewController: UIViewController {
    
    @IBOutlet var Label: UILabel!
    
    @IBOutlet var ukFlag: UITextView!
    
    @IBOutlet var movie: UITextView!
    
    @IBOutlet var piano: UITextView!
    
    @IBOutlet var book: UITextView!
    
    @IBOutlet var dance: UITextView!
    
    @IBOutlet var paint: UITextView!
    
    @IBOutlet var row: UITextView!
    
    @IBOutlet var envelope: UITextView!
    
    @IBOutlet var dragon: UITextView!
    
    @IBOutlet var instagram: UITextView!
    
    
    func londonPuzzle(sender: UIPanGestureRecognizer) {
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
          self.ifCollided()
    
    
    }
    
    
    func misleadOne(sender: UIPanGestureRecognizer) {
    
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
        self.ifCollided()
    
    }
    
    func bestival(sender: UIPanGestureRecognizer) {
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
          self.ifCollided()
    
        }
    
    func rosieProject(sender: UIPanGestureRecognizer) {
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
        self.ifCollided()
    
    }
    
    func misleadTwo(sender: UIPanGestureRecognizer) {
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
        self.ifCollided()
    
    }
    
    func misleadThree(sender: UIPanGestureRecognizer) {
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
        self.ifCollided()
    
    }
    
    func misleadFour(sender: UIPanGestureRecognizer) {
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
        self.ifCollided()
    
    }
    func voucher(sender: UIPanGestureRecognizer) {
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
        self.ifCollided()
    
    }
    
    func welsh(sender: UIPanGestureRecognizer) {
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
        self.ifCollided()
    
    }
    
    func hulk(sender: UIPanGestureRecognizer) {
        let translation = sender.translationInView(self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y + translation.y)
        sender.setTranslation(CGPointZero, inView: self.view)
        self.ifCollided()
    
    }
    
    func ShowAlertWrong(){
    
        let alertController = UIAlertController(title: "Sorry", message:   " Guess again!", preferredStyle: .Alert)
    
        let okAction = UIAlertAction( title: "Ok", style:   UIAlertActionStyle.Default) {
            UIAlertAction in
    
            self.ukFlag.center = CGPointMake(150, 225)
            self.movie.center = CGPointMake(150, 225)
            self.piano.center = CGPointMake(150, 225)
            self.dance.center = CGPointMake(150, 225)
            self.paint.center = CGPointMake(150, 225)
            self.row.center = CGPointMake(150, 225)
            self.envelope.center = CGPointMake(150, 225)
            self.dragon.center = CGPointMake(150, 225)
            self.instagram.center = CGPointMake(150, 225)
        }
    
        let resetAction = UIAlertAction( title: "Reset", style: UIAlertActionStyle.Default) {
            UIALertAction in
    
            self.ukFlag.center = CGPointMake(150, 225)
            self.movie.center = CGPointMake(150, 225)
            self.piano.center = CGPointMake(150, 225)
            self.dance.center = CGPointMake(150, 225)
            self.paint.center = CGPointMake(150, 225)
            self.row.center = CGPointMake(150, 225)
            self.envelope.center = CGPointMake(150, 225)
            self.dragon.center = CGPointMake(150, 225)
            self.instagram.center = CGPointMake(150, 225)
    
        }
    
        alertController.addAction(okAction)
        alertController.addAction(resetAction)
        self.presentViewController(alertController, animated: true, completion: nil)
    
    }
    
    
    
    
    func ShowAlertWin(){
    
    
    
        let alertController = UIAlertController(title: "Congrats🎉", message: " You are correct!👏🏻", preferredStyle: .Alert)
    
        let okAction = UIAlertAction( title: "Ok", style: UIAlertActionStyle.Default) {
            UIAlertAction in
    
            self.book.center = CGPointMake(150, 150)
    
    
        }
    
      /*  let resetAction = UIAlertAction( title: "Reset and hope the mood has changed", style: UIAlertActionStyle.Default) {
            UIALertAction in
    
            self.Angry.center = CGPointMake(150, 150)
        }*/
    
        alertController.addAction(okAction)
       // alertController.addAction(resetAction)
        if presentedViewController !== nil {
            self.presentViewController(alertController, animated: true, completion: nil)
    
        } else{
            self.dismissViewControllerAnimated(false, completion: nil)
            self.presentViewController(alertController, animated: true, completion: nil)
        }
    
    
    
    }
    
    
    
    
    
    
    @IBAction func ifCollided(){
    
    if CGRectIntersectsRect(Label.frame, ukFlag.frame) {
        ShowAlertWrong()
    }
        else if CGRectIntersectsRect(Label.frame, movie.frame){
               ShowAlertWrong()
            } else if CGRectIntersectsRect(Label.frame, piano.frame){
                    ShowAlertWrong()
            }  else if CGRectIntersectsRect(Label.frame, dance.frame){
                ShowAlertWrong()
    } else if CGRectIntersectsRect(Label.frame, paint.frame){
        ShowAlertWrong()
    } else if CGRectIntersectsRect(Label.frame, row.frame){
        ShowAlertWrong()
    } else if CGRectIntersectsRect(Label.frame, envelope.frame){
        ShowAlertWrong()
    } else if CGRectIntersectsRect(Label.frame, dragon.frame){
        ShowAlertWrong()
    } else if CGRectIntersectsRect(Label.frame, instagram.frame){
        ShowAlertWrong()
    } else if CGRectIntersectsRect(Label.frame, book.frame){
        ShowAlertWin()
    }
    
    
    }
    
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        ukFlag.addGestureRecognizer(UIPanGestureRecognizer(target: self,      action: #selector(self.londonPuzzle(_:))))
        movie.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.misleadOne(_:))))
        piano.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.bestival(_:))))
        book.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.rosieProject(_:))))
        dance.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.misleadTwo(_:))))
        paint.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.misleadThree(_:))))
        row.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.misleadFour(_:))))
        envelope.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.voucher(_:))))
        dragon.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.welsh(_:))))
        instagram.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.hulk(_:))))
    
    
    }
    
    }
    
  • CatiaV5
    CatiaV5 almost 8 years
    hey, thanks very much for your answer! It works however, it seems like the alert window pops up twice really quickly...I tried to fix it but I am not sure how...has it something to with it entering a loop twice or something?
  • Nirav D
    Nirav D almost 8 years
    I don't understand what you try to say can you explain a bit more?
  • CatiaV5
    CatiaV5 almost 8 years
    if I drag drop the correct symbol on the label then the alert box opens up twice in a row in quick succession (i.e. alert "wrong" pops up shuts down and pops up again really quick). does my explanation make more sense now? it is really hard to explain...it just opens up , closes and reopens quickly
  • Nirav D
    Nirav D almost 8 years
    Can you make some video or gif and show me so it will be helpful.
  • CatiaV5
    CatiaV5 almost 8 years
    how can I send a gif/video on here? Is it possible to private message you on here?
  • Nirav D
    Nirav D almost 8 years
    It is happening on wrong answer also not only correct one. I think the problem is your method is calling twice i think you can check that using breakpoint. Check and confirm here
  • CatiaV5
    CatiaV5 almost 8 years
    The cause seems to be "self.presentViewController(alertController, animated: true, completion: nil)" in the "else" statement. Not sure how to get around it tho.
  • Nirav D
    Nirav D almost 8 years
    The message is same both the times so i think you don't need to write else part, Just add the alertController, if not presented.
  • CatiaV5
    CatiaV5 almost 8 years
    yeah I have tried to use it without the else statement but this gives me the warning: "Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior"
  • Nirav D
    Nirav D almost 8 years
    I am saying just use if condition presentedViewController == nil then present the controller. There is no need to write else part.
  • CatiaV5
    CatiaV5 almost 8 years
    Thats what I have done. I just used if presentedViewController == nil { self.presentViewController(alertController, animated: true, completion: nil)}
  • Nirav D
    Nirav D almost 8 years
    Have you try to put break point? i think your method is calling twice.
  • CatiaV5
    CatiaV5 almost 8 years
    I am currently trying. I will let you know if I found something.
  • CatiaV5
    CatiaV5 almost 8 years
    Okay I have tried break points at several locations....without success....it seems the issue is the " else" statement...but as I said if I leave it out I will get the warning "...deallocating is not allowed..."...
  • Nirav D
    Nirav D almost 8 years
    That waring you should ignore check this link
  • Nirav D
    Nirav D almost 8 years
    It is giving you because you are not presenting the alertView after initializing. If you want to remove that error try something like this if presentedViewController == nil { then create the alertController instance and present it.
  • CatiaV5
    CatiaV5 almost 8 years
    ahhhhhh!!!! Yeah that was the problem!!! Thank you so much :) now its running perfectly fine :)
  • Dani
    Dani about 6 years
    What if first VC is an alert? We don't want it to get automatically dismissed right away
  • Nirav D
    Nirav D about 6 years
    @DaniSpringer Sorry don't get you, can you please give more details about your question ?
  • Dani
    Dani about 6 years
    Sure. I'm trying to show an alert view controller, and a activity view controller right after it, as soon as the alert is dismissed. Using the shown code above, the alert is shown for a moment and immediately dismissed automatically. (If you might, see last few commits for this: github.com/DaniSpringer/MemeMe1.0/blob/master/MemeMe1.0/…)
  • Nirav D
    Nirav D about 6 years
    @DaniSpringer I have checked the code but what I am not getting is why you are presenting both activity indicator and alert controller one after another. That's why it might be showing alert controller on activity indicator
  • Dani
    Dani about 6 years
    I want to let the user know if the image got saved. For example: they open avc, tap save, get asked permission to access photo library, and deny access. Instead of the default alert error message "data unavailable" I'd like to present a custom alert, with a human message and a link to settings app. The alert itself worked as expected, but as soon as I tried adding it to the avc, it stopped. I've updated the code a bit so if you might take another look, it might help (at least, to understand my logic 😊). Thanks!
  • user689072
    user689072 over 5 years
    Great! Update: "removeFromParentViewContoller()" is changed to "presented.removeFromParent()"