-2

I have an application that displays documents in a UICollectionView. Each UICollectionViewCell has a button (distinct from that carried out by didSelectItemAt). This button brings up a custom popup which I have created using a UIViewController. It is presented Over Current Context. This popup presents a list of options, one including Delete document. When a user selects this latter option, I would like a UIAlertController to appear to confirm delete. This is the issue that I am facing.

Here is my code:

The error that I am getting is:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller .

CUSTOM POPUP (UIViewController)

protocol DismissOptionShowDeleteAlert {
    func showDeleteAlert()
}

class MoreOptionsOnPDFViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{

var showDeleteAlertDelegate: DismissOptionShowDeleteAlert!

/ TAP ON ROW
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){

    ...

     }else if indexPath == [0,4]{ // DELETE DOCUMENT

        DispatchQueue.main.async {
            self.dismiss(animated: true) {
                self.showDeleteAlertDelegate.showDeleteAlert()
            }
        }
    }

    ...

}

UICollectionView:

class CollectionViewFolder: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate ,UICollectionViewDelegateFlowLayout, MoreInfoDocument, MoveFolder, ScanObjectMovedFolder, DismissOptionShowDeleteAlert{

// SHOW DELETE CONFIRMATION ALERT
func showDeleteAlert() {

    Alerts.deleteDocumentConfirm(on: self) {
        // DELETE DOCUMENT FROM SERVER
        print("Delete document ...")
    }
}

}

UIAlertController Struct:

import Foundation
import UIKit

struct Alerts {
private static func showBasicAlert(on vc: UIViewController, with title: String, message: String, action: @escaping (() -> ())){

    let alert =  UIAlertController.init(title: title, message: message, preferredStyle: .alert)
    let okAction = UIAlertAction.init(title: "OK", style: .default) { (UIActionAlert) in

        action()
    }

    let cancelAction = UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil)

    alert.addAction(okAction)
    alert.addAction(cancelAction)
    DispatchQueue.main.async {
        vc.present(vc, animated: true, completion: nil)
    }

}


static func deleteDocumentConfirm(on vc: UIViewController, action: @escaping (() -> ())){
    showBasicAlert(on: vc, with: "Please Confirm Delete", message: "", action: action)
}

}    
Rakesha Shastri
  • 11,053
  • 3
  • 37
  • 50
dean
  • 321
  • 3
  • 17
  • 2
    Possible duplicate of ["Application tried to present modally an active controller"?](https://stackoverflow.com/questions/7429014/application-tried-to-present-modally-an-active-controller) – regina_fallangi Sep 10 '18 at 09:27

3 Answers3

3

It is exactly what your error says. You seem to be presenting the view controller vc instead of the alert from vc

private static func showBasicAlert(on vc: UIViewController, with title: String, message: String, action: @escaping (() -> ())){

    let alert =  UIAlertController.init(title: title, message: message, preferredStyle: .alert)
    let okAction = UIAlertAction.init(title: "OK", style: .default) { (UIActionAlert) in

        action()
    }

    let cancelAction = UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil)

    alert.addAction(okAction)
    alert.addAction(cancelAction)
    DispatchQueue.main.async {
        vc.present(alert, animated: true, completion: nil) // You should be presenting the alert here.
    }

}
Rakesha Shastri
  • 11,053
  • 3
  • 37
  • 50
1

You are presenting wrong. You need to present alert not vc.

Replace below with your code.

struct Alerts {
private static func showBasicAlert(on vc: UIViewController, with title: String, message: String, action: @escaping (() -> ())){

    let alert =  UIAlertController.init(title: title, message: message, preferredStyle: .alert)
    let okAction = UIAlertAction.init(title: "OK", style: .default) { (UIActionAlert) in

        action()
    }

    let cancelAction = UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil)

    alert.addAction(okAction)
    alert.addAction(cancelAction)
    DispatchQueue.main.async {
        vc.present(alert, animated: true, completion: nil)
    }

}
Denis
  • 492
  • 2
  • 15
1

Replace below line

vc.present(vc, animated: true, completion: nil)

to

vc.present(alert, animated: true, completion: nil)

Pankil
  • 635
  • 6
  • 20