Как: Предоставить SKScene доступ к методу dismission() UIKit

#ios #swift #uikit

#iOS #swift #uikit

Вопрос:

Возможно ли получить доступ к dismission() в классе SKScene? Dismiss — это метод, доступный в Apple UIKit. Вот ссылка на официальную документацию Apple по dismiss.

 class GameScene: SKScene {

}
  

Попытка запустить dismission из примера IBAction:

     @IBAction func dismissTapped(_ sender: Any) {
     //figure out how to dismiss
    }
  

Dismiss обычно используется следующим образом —

 dismiss(animated: true, completion: nil)
  

Ответ №1:

dismiss это метод в UIViewController, а не в SKScene. Однако у вашей сцены действительно есть view свойство, которое является содержащим ее представлением (которое является SKView , которое является UIView , которое является UIResponder ). Вы можете использовать next метод представления, унаследованный от UIResponder , чтобы пройти вверх по цепочке ответчиков, пока не нажмете на первый контроллер представления (потому что UIViewController это также UIResponder ):

 extension UIResponder {
    func firstParent<T: UIResponder>(ofType type: T.Type ) -> T? {
        return next as? T ?? next.flatMap { $0.firstParent(ofType: type) }
    }
}
  
 //Use in your SKScene like so
view?.firstParent(ofType: UIViewController.self)?.dismiss(animated: true, completion: nil)
  

Комментарии:

1. Не могли бы вы подробнее объяснить этот метод firstParent? После добавления расширения за пределами класса и добавления этой строки под функцией в мой IBAction выдается сообщение об ошибке : нераспознанный селектор, отправленный в экземпляр.

2. ОТРЕДАКТИРОВАНО ВЫШЕ. Извините, я пропустил . self после UIViewController. В любом случае firstParent рекурсивно проходит вверх по цепочке ответчиков, пока не найдет тип пользовательского интерфейса, который вы ищете (обычно UIView или UIViewController), или он попадает в окно. Это делает типобезопасный способ с использованием универсального. Вы можете передать UIViewController.self или yourviewcontroller class.self в зависимости от того, какой тип объекта вы хотите получить обратно. В этом случае UIViewController.self является достаточным, поскольку dismiss определен в UIViewController.

3. спасибо за обновление! отличный ответ, просто хотел немного больше понять это, что я сейчас так ценю. После обновления кода — Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SKView dismissTapped:]: unrecognized selector sent to instance 0x7fcf0e814800'

4. у вас есть идея, почему NSInvalidArgumentException здесь будут уволены? Сейчас исследую, но пытаюсь дополнить этот вопрос исключительным ответом. Еще раз спасибо за помощь

5. Похоже, что это не связанная ошибка. Возможно, у вас сломан выход в вашей раскадровке или вызываемом интерфейсе dismissTapped ? Откройте раскадровку / перо и выберите ViewController. затем нажмите на инспектор подключений справа и посмотрите, не разорвано ли соединение для dismissTapped