Как передать замыкание в параметре sender executeSegue? - PullRequest
0 голосов
/ 19 июня 2019

В моем iOS приложении я хотел бы задать пользователю вопрос, а затем предпринять некоторые действия в зависимости от ответа.

Во многих других средах программирования я бы использовал модальноедиалоговое окно, которое ожидает от пользователя ввода результата, а затем возвращает этот результат в основной код.Но, насколько мне известно, инфраструктура UIKit не содержит таких модальных диалогов .Вместо этого я использую модальный segue , но так как вызов performSegue немедленно возвращается, программирование становится несколько грязным ...

performSegue имеет параметр отправителя вида Any?,Могу ли я использовать этот параметр для передачи замыкания с кодом, который будет выполнен при выходе пользователя из очереди?И если да, то как?

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Я не думаю, что это возможно с performSegue, но вы можете использовать prepareForSegue для отправки значений при выполнении перехода.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {        
    let vc = segue.destination as! MyViewController
    vc.myParameter = myValue

}

но если вы просто хотите дать пользователю диалог и ждать ответа, есть другой способ сделать это.

Вы можете создать viewController с фоном по умолчанию, который сделает его скрытым, а затем добавить View внутри него и настроить его так, как вы хотите, вы можете рассматривать его как Alert. и затем инициируйте его, когда вы хотите запросить данные у пользователя.

let vc = self.storyboard?.instantiateViewController(withIdentifier: "alert") as! AlertViewController
vc.definesPresentationContext = true
vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
//Here you can pass data into the viewController you're initiating
vc.myParameter = myValue
self.present(vc,animated: false,completion: nil)

таким образом, UIView, настроенный вами в viewController, будет выглядеть как обычное предупреждение для текущего viewController.

0 голосов
/ 19 июня 2019

На момент написания этого вопроса было три отрицательных голоса!Я не понимаю почему.На мой взгляд, мой вопрос четко сформулирован.

Можно использовать performSegue и prepare(for:sender:).Но использование instantiateViewController требует меньше работы по настройке.

Вот решение , основанное на ответе Ясира :

В раскадровке я создал контроллер представления (PawnPromotionVC) с полупрозрачным белым фоновым представлением и непрозрачным меньшим вложенным представлением, содержащим «диалог».Контроллер представления имеет атрибут onExit, объявленный следующим образом:

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

Ниже представлен обработчик действий для нажатий кнопок в этом контроллере представления (кстати, цель «диалога» состоит в том, чтобы спроситьпользователь, какую шахматную фигуру следует продвигать пешке):

  @IBAction func pieceButtonTapped(_ sender: UIButton) {
        let piece = Piece(rawValue: sender.tag)!

        if let run = onExit {
            run( piece )
        }
        dismiss(animated: true, completion: nil)
    }

Чтобы открыть диалоговое окно, я вызываю

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

из моего mainViewController .Функция runPawnPromotionDialog, также реализованная в mainViewController, практически реализована в соответствии с предложением 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)
    }
...