2016-09-13 6 views
1

Я пытаюсь написать протокол и пользовательский класс 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 равны нулю, но сам контроллер не является. Это плохой шаблон дизайна, или я просто пропустил что-то простое?

ответ

1

Контролируемый контроллер просмотра - это одно событие. Это загруженное изображение - другое.

Свойство контроллера изображения загружается лениво, а выходы построены и подключены в этой точке. Вот почему viewDidLoad() - вещь.

Если вы хотите, чтобы представление было готово к вам, вы можете сначала вызвать loadViewIfNeeded() на контроллере.

0

диагностируется проблема ... контроллер назначения был загружен, но я забыл добавить вид контроллера-адресата к окну в классе Segue:

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 

       UIApplication.shared.keyWindow?.insertSubview(self.destination.view, aboveSubview: self.source.view) 
       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 
       UIApplication.shared.keyWindow?.insertSubview(self.destination.view, aboveSubview: self.source.view) 
       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) 
        } 
       } 
      } 
     } 
    } 
} 
Смежные вопросы