Segue personnalisé dans Swift

@objc(SEPushNoAnimationSegue) class SEPushNoAnimationSegue: UIStoryboardSegue { override func perform () { self.sourceViewController.navigationController.pushViewController(self.destinationViewController, animated:false) } } 

Dans le code ci-dessus, j'ai 2 questions: 1). il a une erreur de compilation: 'UINavigationController!' n'a pas de membre nommé 'pushViewController'

Mais dans cette class, il a fait une méthode pushViewController.

2). Je dois append l'annotation: @objc (SEPushNoAnimationSegue), sinon, dans le storyboard, il ne reconnaît que le nom généré randomment, comme, _tcxxxxSEPushNoAnimationSegue.

pourquoi ces 2 problèmes se produisent ici?

Numéro 1

UIStoryboardSegue a un défaut irritant: ses propriétés sourceViewController et destinationViewController sont tapées comme AnyObject! (c'est le cas même dans Objective-C (type d'ID)) et non comme UIViewController , comme il se doit.

Ce même défaut crée des ravages dans votre code parfait et simple. Voici comment le réécrire afin de corriger les erreurs de compilation:

 @objc(SEPushNoAnimationSegue) class SEPushNoAnimationSegue: UIStoryboardSegue { override func perform () { let src = self.sourceViewController as UIViewController let dst = self.destinationViewController as UIViewController src.navigationController.pushViewController(dst, animated:false) } } 

REMARQUE: Apple a corrigé cette sourceViewController dans iOS 9. sourceViewController et destinationViewController sont maintenant correctement déclarés comme UIViewController .

Numéro 2

Le compilateur Swift stocke ses symboles en utilisant son propre nom mangling , et le bon vieux 'Objective-C ne le reconnaît pas dans Xcode. L'utilisation d'un @obj() explicite résout le problème.

Cela fonctionne bien pour moi

 @objc(SEPushNoAnimationSegue) class SEPushNoAnimationSegue: UIStoryboardSegue { override func perform() { let sourceViewController = self.sourceViewController as UIViewController let destinationViewController = self.destinationViewController as UIViewController sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil) } } 

Encore mieux:

 import UIKit class CustomSegue: UIStoryboardSegue { override func perform() { self.sourceViewController.presentViewController(self.destinationViewController as UIViewController, animated: false, completion: nil) } } 

Swift 3.0:

 import UIKit class CustomNoAnimationSegue: UIStoryboardSegue { override func perform() { if let navigation = source.navigationController { navigation.pushViewController(destination, animated: false) } } }