Пользовательский Segue в Swift
@objc(SEPushNoAnimationSegue)
class SEPushNoAnimationSegue: UIStoryboardSegue {
override func perform () {
self.sourceViewController.navigationController.pushViewController(self.destinationViewController, animated:false)
}
}
В приведенном выше коде у меня есть 2 вопроса:
1). он имеет ошибку компиляции:
'UINavigationController! не имеет члена с именем 'pushViewController'
Но в этом классе он имеет метод pushViewController.
2). Я должен добавить аннотацию: @objc (SEPushNoAnimationSegue),
в противном случае в раскадровке он распознает только случайное сгенерированное имя, например, _tcxxxxSEPushNoAnimationSegue.
почему эти два вопроса происходят здесь?
Ответы
Ответ 1
Проблема №1
UIStoryboardSegue имеет раздражающий недостаток: его свойства sourceViewController и destinationViewController набираются как AnyObject!
(этот случай даже в Objective-C (тип идентификатора)), а не как UIViewController
, как и должно быть.
Тот же недостаток создает хаос в вашем совершенном и простом коде. Здесь, как переписать его, чтобы исправить ошибки компиляции:
@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)
}
}
ПРИМЕЧАНИЕ. Apple исправила эту вещь в iOS 9. sourceViewController
и destinationViewController
теперь корректно объявлены как UIViewController
.
Проблема № 2
Компилятор Swift сохраняет свои символы, используя свое собственное название mangling, а good ol Objective-C не распознает его в Xcode. Использование явного @obj()
решает проблему.
Ответ 2
Это отлично работает для меня
@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)
}
}
Ответ 3
Даже лучше:
import UIKit
class CustomSegue: UIStoryboardSegue {
override func perform() {
self.sourceViewController.presentViewController(self.destinationViewController as UIViewController, animated: false, completion: nil)
}
}
Ответ 4
Swift 3.0:
import UIKit
class CustomNoAnimationSegue: UIStoryboardSegue {
override func perform() {
if let navigation = source.navigationController {
navigation.pushViewController(destination, animated: false)
}
}
}