Я пытаюсь написать протокол и пользовательский класс UIStoryboardSegue, который позволит мне легко реализовать пользовательские переходы в моих UIViewControllers:Когда контроллер назначения назначения инициализируется во время segue?
public protocol TransitionController
{
var transitionDurationIn: CFTimeInterval { get }
var transitionDurationOut: CFTimeInterval { get }
func prepareTransitionIn()
func prepareTransitionOut()
func performTransitionIn(finished: @escaping() -> Void)
func performTransitionOut(finished: @escaping() -> Void)
}
class JFTransitionControllerSegue: UIStoryboardSegue {
override func perform() {
let defaultTransitionDuration : CFTimeInterval = 1.5
if let dvc = self.destination as? TransitionController {
dvc.prepareTransitionIn()
}
else {
// Default transition
self.destination.view.alpha = 0
}
if let svc = self.source as? TransitionController {
svc.prepareTransitionOut()
svc.performTransitionOut(){() in
if let dvc = self.destination as? TransitionController {
dvc.performTransitionIn(){() in
self.source.present(self.destination, animated: false, completion: nil)
}
}
else {
// Default transition for the destination controller
UIView.animate(withDuration: defaultTransitionDuration, animations: {
self.destination.view.alpha = 1
}) { (Finished) in
self.source.present(self.destination, animated: false, completion: nil)
}
}
}
}
else
{
// Default transition for the source controller
UIView.animate(withDuration: defaultTransitionDuration, animations: {
self.source.view.alpha = 0
}) { (Finished) in
if let dvc = self.destination as? TransitionController {
dvc.performTransitionIn(){() in
self.source.present(self.destination, animated: false, completion: nil)
}
}
else {
// Default transition for the destination controller
UIView.animate(withDuration: defaultTransitionDuration, animations: {
self.destination.view.alpha = 1
}) { (Finished) in
self.source.present(self.destination, animated: false, completion: nil)
}
}
}
}
}
}
class TestController: UIViewController, TransitionController {
@IBOutlet weak var form_username: UITextField!
// MARK: - TransitionController Protocol
var transitionDurationIn : CFTimeInterval {return 1.0}
var transitionDurationOut : CFTimeInterval {return 1.0}
func prepareTransitionIn()
{
//self.view.alpha = 0 // no fade in if you uncomment
form_username.alpha = 0 // nil
}
func prepareTransitionOut()
{
self.view.alpha = 1 // works
}
func performTransitionIn(finished: @escaping() -> Void)
{
UIView.animate(withDuration: self.transitionDurationIn, animations: {
//self.view.alpha = 1 // no fade in if you uncomment
self.form_username.alpha = 1 // nil, crashes
}) { (Finished) in
finished()
}
}
func performTransitionOut(finished: @escaping() -> Void)
{
UIView.animate(withDuration: self.transitionDurationOut, animations: {
self.view.alpha = 0 // fades out correctly
}) { (Finished) in
finished()
}
}
}
В принципе, вы просто реализовать протокол в любом UIViewController вы хотите, то сделайте Сегмент класса JFTransitionControllerSegue. В функции performTransitionIn
вы можете просто сделать что-то вроде UIView.animate
и изменить альфа или что угодно. Проблема, с которой я сталкиваюсь, заключается в том, что целевой сегмент просто появляется, а не переходит правильно. Из того, что я могу сказать при отладке, он не полностью инициализирован - переменные IBOutlet равны нулю, но сам контроллер не является. Это плохой шаблон дизайна, или я просто пропустил что-то простое?