Search code examples
iosswiftmodal-dialogclosuressegue

How to pass a closure in performSegue's sender parameter?


In my iOS App, I would like to ask the user a question and then take some actions depending on the answer.

In many other programming frameworks I would have used a modal dialog that waits for the user to enter the result and then returns that result to the main code. But, to my knowledge, the UIKit framework does not contain such modal dialogs . Instead I use a modal segue, but since the call to performSegue returns immediately the programming becomes somewhat messy...

The performSegue has a sender parameter of kind Any?. Can I use that parameter to pass a closure with the code to be executed when the user exits the segue? And, if so, how?


Solution

  • At the time of writing this question has three down votes! I can't see why. In my opinion my question is clearly stated.

    It is possible to use performSegue and prepare(for:sender:). But using instantiateViewController requires less setup work.

    Here is a solution based on Yasser's answer:

    In storyboard I created a view controller (PawnPromotionVC) with a semi transparent white background view, and a non transparent smaller sub view containing the "dialog". The view controller has a onExit attribute declared as follows:

       var onExit : ((Piece) -> Void)?
    

    Below is the action handler for button tapps in that view controller (by the way, the objective of the "dialog" is to asks the user what chess piece a pawn should be promoted to):

      @IBAction func pieceButtonTapped(_ sender: UIButton) {
            let piece = Piece(rawValue: sender.tag)!
    
            if let run = onExit {
                run( piece )
            }
            dismiss(animated: true, completion: nil)
        }
    

    To launch the dialog I call

      if ... {
          runPawnPromotionDialog(){
              (piece:Piece) in
               print("the pawn should be promoted to a \(piece)" )
               ...
               ...
          }
      }
    

    from my mainViewController. The function runPawnPromotionDialog, also implemented in the mainViewController, is almost implemented as suggested by Yasser:

      func runPawnPromotionDialog( onExit: @escaping (Piece) -> Void ){
    
            let vc = self.storyboard?.instantiateViewController(withIdentifier: "PawnPromotionVC") as! PawnPromotionVC
    
            vc.definesPresentationContext = true
            vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
            vc.modalTransitionStyle = .crossDissolve
    
            vc.onExit = onExit
            self.present(vc,animated: false,completion: nil)
        }