Commit 19664a2f by Daniel Dahan

partial work completed for reworking Motion and MotionController

parent baf1bf57
...@@ -198,8 +198,8 @@ ...@@ -198,8 +198,8 @@
96AEB6691EE4610F009A3BE0 /* Debug Plugin */, 96AEB6691EE4610F009A3BE0 /* Debug Plugin */,
96AEB66D1EE4610F009A3BE0 /* Extensions */, 96AEB66D1EE4610F009A3BE0 /* Extensions */,
96AEB6771EE4610F009A3BE0 /* Motion.swift */, 96AEB6771EE4610F009A3BE0 /* Motion.swift */,
963150D41EE51C7A002B0D42 /* MotionAnimation.swift */,
96AEB6781EE4610F009A3BE0 /* MotionController.swift */, 96AEB6781EE4610F009A3BE0 /* MotionController.swift */,
963150D41EE51C7A002B0D42 /* MotionAnimation.swift */,
96AEB6791EE4610F009A3BE0 /* MotionContext.swift */, 96AEB6791EE4610F009A3BE0 /* MotionContext.swift */,
96AEB67A1EE4610F009A3BE0 /* MotionIndependentController.swift */, 96AEB67A1EE4610F009A3BE0 /* MotionIndependentController.swift */,
96AEB67B1EE4610F009A3BE0 /* MotionTransition.swift */, 96AEB67B1EE4610F009A3BE0 /* MotionTransition.swift */,
......
...@@ -410,6 +410,11 @@ extension MotionCoreAnimationViewContext { ...@@ -410,6 +410,11 @@ extension MotionCoreAnimationViewContext {
return values return values
} }
/**
Moves a layer's animation to a given elapsed time.
- Parameter layer: A CALayer.
- Parameter elapsedTime: A TimeInterval.
*/
fileprivate func seek(layer: CALayer, elapsedTime: TimeInterval) { fileprivate func seek(layer: CALayer, elapsedTime: TimeInterval) {
let timeOffset = elapsedTime - targetState.delay let timeOffset = elapsedTime - targetState.delay
for (key, anim) in layer.animations { for (key, anim) in layer.animations {
......
...@@ -38,13 +38,13 @@ public class MotionDebugPlugin: MotionPlugin { ...@@ -38,13 +38,13 @@ public class MotionDebugPlugin: MotionPlugin {
var updating = false var updating = false
override public func animate(fromViews: [UIView], toViews: [UIView]) -> TimeInterval { override public func animate(fromViews: [UIView], toViews: [UIView]) -> TimeInterval {
if Motion.shared.forceNotInteractive { return 0 } if Motion.shared.forceNonInteractive { return 0 }
var hasArc = false var hasArc = false
for v in context.fromViews + context.toViews where context[v]?.arc != nil && context[v]?.position != nil { for v in context.fromViews + context.toViews where context[v]?.arc != nil && context[v]?.position != nil {
hasArc = true hasArc = true
break break
} }
let debugView = MotionDebugView(initialProcess: Motion.shared.presenting ? 0.0 : 1.0, showCurveButton:hasArc, showOnTop:MotionDebugPlugin.showOnTop) let debugView = MotionDebugView(initialProcess: Motion.shared.isPresenting ? 0.0 : 1.0, showCurveButton:hasArc, showOnTop:MotionDebugPlugin.showOnTop)
debugView.frame = Motion.shared.container.bounds debugView.frame = Motion.shared.container.bounds
debugView.delegate = self debugView.delegate = self
UIApplication.shared.keyWindow!.addSubview(debugView) UIApplication.shared.keyWindow!.addSubview(debugView)
...@@ -81,7 +81,7 @@ public class MotionDebugPlugin: MotionPlugin { ...@@ -81,7 +81,7 @@ public class MotionDebugPlugin: MotionPlugin {
extension MotionDebugPlugin:MotionDebugViewDelegate { extension MotionDebugPlugin:MotionDebugViewDelegate {
public func onDone() { public func onDone() {
guard let debugView = debugView else { return } guard let debugView = debugView else { return }
let seekValue = Motion.shared.presenting ? debugView.progress : 1.0 - debugView.progress let seekValue = Motion.shared.isPresenting ? debugView.progress : 1.0 - debugView.progress
if seekValue > 0.5 { if seekValue > 0.5 {
Motion.shared.end() Motion.shared.end()
} else { } else {
...@@ -90,7 +90,7 @@ extension MotionDebugPlugin:MotionDebugViewDelegate { ...@@ -90,7 +90,7 @@ extension MotionDebugPlugin:MotionDebugViewDelegate {
} }
public func onProcessSliderChanged(progress: Float) { public func onProcessSliderChanged(progress: Float) {
let seekValue = Motion.shared.presenting ? progress : 1.0 - progress let seekValue = Motion.shared.isPresenting ? progress : 1.0 - progress
Motion.shared.update(progress: Double(seekValue)) Motion.shared.update(progress: Double(seekValue))
} }
......
...@@ -235,11 +235,11 @@ class DefaultAnimationPreprocessor: BasePreprocessor { ...@@ -235,11 +235,11 @@ class DefaultAnimationPreprocessor: BasePreprocessor {
override func process(fromViews: [UIView], toViews: [UIView]) { override func process(fromViews: [UIView], toViews: [UIView]) {
guard let motion = motion else { return } guard let motion = motion else { return }
var defaultAnimation = motion.defaultAnimation var defaultAnimation = motion.defaultAnimation
let inNavigationController = motion.inNavigationController let inNavigationController = motion.isNavigationController
let inTabBarController = motion.inTabBarController let inTabBarController = motion.isTabBarController
let toViewController = motion.toViewController let toViewController = motion.toViewController
let fromViewController = motion.fromViewController let fromViewController = motion.fromViewController
let presenting = motion.presenting let presenting = motion.isPresenting
let fromOverFullScreen = motion.fromOverFullScreen let fromOverFullScreen = motion.fromOverFullScreen
let toOverFullScreen = motion.toOverFullScreen let toOverFullScreen = motion.toOverFullScreen
let toView = motion.toView let toView = motion.toView
......
...@@ -312,6 +312,7 @@ extension UIViewController { ...@@ -312,6 +312,7 @@ extension UIViewController {
/** /**
Replace the current view controller with another view controller on the Replace the current view controller with another view controller on the
navigation/modal stack. navigation/modal stack.
- Parameter with next: A UIViewController.
*/ */
public func motion_replaceViewController(with next: UIViewController) { public func motion_replaceViewController(with next: UIViewController) {
guard !Motion.shared.isTransitioning else { guard !Motion.shared.isTransitioning else {
...@@ -328,7 +329,7 @@ extension UIViewController { ...@@ -328,7 +329,7 @@ extension UIViewController {
} }
if navigationController.isMotionEnabled { if navigationController.isMotionEnabled {
Motion.shared.forceNotInteractive = true Motion.shared.forceNonInteractive = true
} }
navigationController.setViewControllers(v, animated: true) navigationController.setViewControllers(v, animated: true)
......
...@@ -41,25 +41,23 @@ import UIKit ...@@ -41,25 +41,23 @@ import UIKit
func update(progress:Double) func update(progress:Double)
func end() func end()
func cancel() func cancel()
func apply(modifiers:[MotionTransition], to view:UIView) func apply(transitions: [MotionTransition], to view: UIView)
``` ```
*/ */
public class Motion: MotionController { public class Motion: MotionController {
// MARK: Shared Access
/// Shared singleton object for controlling the transition /// Shared singleton object for controlling the transition
public static let shared = Motion() public static let shared = Motion()
// MARK: Properties /// Source view controller.
public internal(set) var fromViewController: UIViewController?
/// destination view controller /// Destination view controller.
public internal(set) var toViewController: UIViewController? public internal(set) var toViewController: UIViewController?
/// source view controller
public internal(set) var fromViewController: UIViewController?
/// whether or not we are presenting the destination view controller
public internal(set) var presenting = true
/// progress of the current transition. 0 if no transition is happening /// Whether or not we are presenting the destination view controller.
public internal(set) var isPresenting = true
/// Progress of the current transition, 0 if a transition is not happening.
public override var progress: Double { public override var progress: Double {
didSet { didSet {
if isTransitioning { if isTransitioning {
...@@ -68,107 +66,108 @@ public class Motion: MotionController { ...@@ -68,107 +66,108 @@ public class Motion: MotionController {
} }
} }
public var isAnimating: Bool = false /// Indicates whether the transition is animating or not.
/// a UIViewControllerContextTransitioning object provided by UIKit, public var isAnimating = false
/// might be nil when isTransitioning. This happens when calling motionReplaceViewController
/**
A UIViewControllerContextTransitioning object provided by UIKit, which
might be nil when isTransitioning. This happens when calling motion_replaceViewController
*/
internal weak var transitionContext: UIViewControllerContextTransitioning? internal weak var transitionContext: UIViewControllerContextTransitioning?
/// A reference to a fullscreen snapshot.
internal var fullScreenSnapshot: UIView! internal var fullScreenSnapshot: UIView!
internal var defaultAnimation: MotionDefaultAnimationType = .auto /// Default animation type.
internal var containerColor: UIColor? internal var defaultAnimation = MotionDefaultAnimationType.auto
// By default, Motion will always appear to be interactive to UIKit. This forces it to appear non-interactive. /// The color of the transitioning container.
// Used when doing a motion_replaceViewController within a UINavigationController, to fix a bug with internal var containerBackgroundColor: UIColor?
// UINavigationController.setViewControllers not able to handle interactive transition
internal var forceNotInteractive = false
/**
By default, Motion will always appear to be interactive to UIKit. This forces it to appear non-interactive.
Used when doing a motion_replaceViewController within a UINavigationController, to fix a bug with
UINavigationController.setViewControllers not able to handle interactive transitions.
*/
internal var forceNonInteractive = false
/// Inserts the to-views first.
internal var insertToViewFirst = false internal var insertToViewFirst = false
internal var inNavigationController = false /// Indicates whether a UINavigationController is transitioning.
internal var inTabBarController = false internal var isNavigationController = false
internal var inContainerController: Bool {
return inNavigationController || inTabBarController /// Indicates whether a UITabBarController is transitioning.
internal var isTabBarController = false
/// Indicates whether a UINavigationController or UITabBarController is transitioning.
internal var isContainerController: Bool {
return isNavigationController || isTabBarController
}
/// Indicates whether the from view controller is full screen.
internal var fromOverFullScreen: Bool {
return !isContainerController && (.overFullScreen == fromViewController!.modalPresentationStyle || .overCurrentContext == fromViewController!.modalPresentationStyle)
} }
/// Indicates whether the to view controller is full screen.
internal var toOverFullScreen: Bool { internal var toOverFullScreen: Bool {
return !inContainerController && (toViewController!.modalPresentationStyle == .overFullScreen || toViewController!.modalPresentationStyle == .overCurrentContext) return !isContainerController && (.overFullScreen == toViewController!.modalPresentationStyle || .overCurrentContext == toViewController!.modalPresentationStyle)
} }
internal var fromOverFullScreen: Bool {
return !inContainerController && (fromViewController!.modalPresentationStyle == .overFullScreen || fromViewController!.modalPresentationStyle == .overCurrentContext) /// A reference to the from-view, fromViewController.view.
internal var fromView: UIView {
return fromViewController!.view
} }
internal var toView: UIView { return toViewController!.view } /// A reference to the to-view, toViewController.view.
internal var fromView: UIView { return fromViewController!.view } internal var toView: UIView {
return toViewController!.view
}
internal override init() { super.init() } /// An initializer.
internal override init() {
super.init()
}
} }
public extension Motion { public extension Motion {
/// Turn off built-in animations for the next transition.
/// Turn off built-in animation for next transition
func disableDefaultAnimationForNextTransition() { func disableDefaultAnimationForNextTransition() {
defaultAnimation = .none defaultAnimation = .none
} }
/// Set the default animation for next transition /**
/// This usually overrides rootView's motionTransitions during the transition Set the default animation for the next transition. This may override the
/// root-view's motionTransitions during the transition.
/// - Parameter animation: animation type - Parameter animation: A MotionDefaultAnimationType.
*/
func setDefaultAnimationForNextTransition(_ animation: MotionDefaultAnimationType) { func setDefaultAnimationForNextTransition(_ animation: MotionDefaultAnimationType) {
defaultAnimation = animation defaultAnimation = animation
} }
/// Set the container color for next transition /**
/// Set the container background color for the next transition.
/// - Parameter color: container color - Parameter _ color: An optional UIColor.
func setContainerColorForNextTransition(_ color: UIColor?) { */
containerColor = color func setContainerBackgroundColorForNextTransition(_ color: UIColor?) {
containerBackgroundColor = color
} }
} }
// internal methods for transition
internal extension Motion { internal extension Motion {
/// Starts the transition animation.
func start() { func start() {
guard isTransitioning else { return } guard isTransitioning else {
if let fvc = fromViewController, let tvc = toViewController { return
closureProcessForMotionDelegate(vc: fvc) {
$0.motionWillStartTransition?()
$0.motionWillStartAnimatingTo?(viewController: tvc)
}
closureProcessForMotionDelegate(vc: tvc) {
$0.motionWillStartTransition?()
$0.motionWillStartAnimatingFrom?(viewController: fvc)
}
}
// take a snapshot to hide all the flashing that might happen
fullScreenSnapshot = transitionContainer.window?.snapshotView(afterScreenUpdates: true) ?? fromView.snapshotView(afterScreenUpdates: true)
(transitionContainer.window ?? transitionContainer)?.addSubview(fullScreenSnapshot)
if let oldSnapshot = fromViewController?.motionStoredSnapshot {
oldSnapshot.removeFromSuperview()
fromViewController?.motionStoredSnapshot = nil
}
if let oldSnapshot = toViewController?.motionStoredSnapshot {
oldSnapshot.removeFromSuperview()
toViewController?.motionStoredSnapshot = nil
} }
prepareViewControllers()
prepareSnapshotView()
prepareForTransition() prepareForTransition()
insert(preprocessor: DefaultAnimationPreprocessor(motion: self), before: DurationPreprocessor.self) prepareMotionContext()
prepareToView()
context.loadViewAlpha(rootView: toView) prepareViewHierarchy()
context.loadViewAlpha(rootView: fromView)
container.addSubview(toView)
container.addSubview(fromView)
toView.frame = fromView.frame
toView.updateConstraints()
toView.setNeedsLayout()
toView.layoutIfNeeded()
context.set(fromViews: fromView.flattenedViewHierarchy, toViews: toView.flattenedViewHierarchy)
processContext() processContext()
prepareForAnimation() prepareForAnimation()
...@@ -178,11 +177,11 @@ internal extension Motion { ...@@ -178,11 +177,11 @@ internal extension Motion {
#if os(tvOS) #if os(tvOS)
animate() animate()
#else #else
if inNavigationController { if isNavigationController {
// When animating within navigationController, we have to dispatch later into the main queue. // When animating within navigationController, we have to dispatch later into the main queue.
// otherwise snapshots will be pure white. Possibly a bug with UIKit // otherwise snapshots will be pure white. Possibly a bug with UIKit
DispatchQueue.main.async { DispatchQueue.main.async { [weak self] in
self.animate() self?.animate()
} }
} else { } else {
animate() animate()
...@@ -193,8 +192,8 @@ internal extension Motion { ...@@ -193,8 +192,8 @@ internal extension Motion {
override func animate() { override func animate() {
context.unhide(view: toView) context.unhide(view: toView)
if let containerColor = containerColor { if let containerBackgroundColor = containerBackgroundColor {
container.backgroundColor = containerColor container.backgroundColor = containerBackgroundColor
} else if !toOverFullScreen && !fromOverFullScreen { } else if !toOverFullScreen && !fromOverFullScreen {
container.backgroundColor = toView.backgroundColor container.backgroundColor = toView.backgroundColor
} }
...@@ -202,6 +201,7 @@ internal extension Motion { ...@@ -202,6 +201,7 @@ internal extension Motion {
if fromOverFullScreen { if fromOverFullScreen {
insertToViewFirst = true insertToViewFirst = true
} }
for animator in animators { for animator in animators {
if let animator = animator as? MotionHasInsertOrder { if let animator = animator as? MotionHasInsertOrder {
animator.insertToViewFirst = insertToViewFirst animator.insertToViewFirst = insertToViewFirst
...@@ -209,27 +209,31 @@ internal extension Motion { ...@@ -209,27 +209,31 @@ internal extension Motion {
} }
super.animate() super.animate()
fullScreenSnapshot!.removeFromSuperview() fullScreenSnapshot!.removeFromSuperview()
} }
override func complete(finished: Bool) { override func complete(finished: Bool) {
guard isTransitioning else { return } guard isTransitioning else {
return
}
context.clean() context.clean()
if finished && presenting && toOverFullScreen {
if finished && isPresenting && toOverFullScreen {
// finished presenting a overFullScreen VC // finished presenting a overFullScreen VC
context.unhide(rootView: toView) context.unhide(rootView: toView)
context.removeSnapshots(rootView: toView) context.removeSnapshots(rootView: toView)
context.storeViewAlpha(rootView: fromView) context.storeViewAlpha(rootView: fromView)
fromViewController!.motionStoredSnapshot = container fromViewController!.motionStoredSnapshot = container
fromView.removeFromSuperview() fromView.removeFromSuperview()
fromView.addSubview(container) fromView.addSubview(container)
} else if !finished && !presenting && fromOverFullScreen { } else if !finished && !isPresenting && fromOverFullScreen {
// cancelled dismissing a overFullScreen VC // cancelled dismissing a overFullScreen VC
context.unhide(rootView: fromView) context.unhide(rootView: fromView)
context.removeSnapshots(rootView: fromView) context.removeSnapshots(rootView: fromView)
context.storeViewAlpha(rootView: toView) context.storeViewAlpha(rootView: toView)
toViewController!.motionStoredSnapshot = container toViewController!.motionStoredSnapshot = container
toView.removeFromSuperview() toView.removeFromSuperview()
toView.addSubview(container) toView.addSubview(container)
...@@ -243,12 +247,13 @@ internal extension Motion { ...@@ -243,12 +247,13 @@ internal extension Motion {
if (toOverFullScreen && finished) || (fromOverFullScreen && !finished) { if (toOverFullScreen && finished) || (fromOverFullScreen && !finished) {
transitionContainer.addSubview(finished ? fromView : toView) transitionContainer.addSubview(finished ? fromView : toView)
} }
transitionContainer.addSubview(finished ? toView : fromView) transitionContainer.addSubview(finished ? toView : fromView)
if presenting != finished, !inContainerController { if isPresenting != finished, !isContainerController {
// only happens when present a .overFullScreen VC // only happens when present a .overFullScreen VC
// bug: http://openradar.appspot.com/radar?id=5320103646199808 // bug: http://openradar.appspot.com/radar?id=5320103646199808
UIApplication.shared.keyWindow!.addSubview(presenting ? fromView : toView) UIApplication.shared.keyWindow!.addSubview(isPresenting ? fromView : toView)
} }
// use temp variables to remember these values // use temp variables to remember these values
...@@ -261,10 +266,10 @@ internal extension Motion { ...@@ -261,10 +266,10 @@ internal extension Motion {
transitionContext = nil transitionContext = nil
fromViewController = nil fromViewController = nil
toViewController = nil toViewController = nil
containerColor = nil containerBackgroundColor = nil
inNavigationController = false isNavigationController = false
inTabBarController = false isTabBarController = false
forceNotInteractive = false forceNonInteractive = false
insertToViewFirst = false insertToViewFirst = false
defaultAnimation = .auto defaultAnimation = .auto
...@@ -272,63 +277,143 @@ internal extension Motion { ...@@ -272,63 +277,143 @@ internal extension Motion {
if finished { if finished {
if let fvc = fvc, let tvc = tvc { if let fvc = fvc, let tvc = tvc {
closureProcessForMotionDelegate(vc: fvc) { processForMotionDelegate(viewController: fvc) {
$0.motionDidEndAnimatingTo?(viewController: tvc) $0.motionDidEndAnimatingTo?(viewController: tvc)
$0.motionDidEndTransition?() $0.motionDidEndTransition?()
} }
closureProcessForMotionDelegate(vc: tvc) { processForMotionDelegate(viewController: tvc) {
$0.motionDidEndAnimatingFrom?(viewController: fvc) $0.motionDidEndAnimatingFrom?(viewController: fvc)
$0.motionDidEndTransition?() $0.motionDidEndTransition?()
} }
} }
tContext?.finishInteractiveTransition() tContext?.finishInteractiveTransition()
} else { } else {
if let fvc = fvc, let tvc = tvc { if let fvc = fvc, let tvc = tvc {
closureProcessForMotionDelegate(vc: fvc) { processForMotionDelegate(viewController: fvc) {
$0.motionDidCancelAnimatingTo?(viewController: tvc) $0.motionDidCancelAnimatingTo?(viewController: tvc)
$0.motionDidCancelTransition?() $0.motionDidCancelTransition?()
} }
closureProcessForMotionDelegate(vc: tvc) { processForMotionDelegate(viewController: tvc) {
$0.motionDidCancelAnimatingFrom?(viewController: fvc) $0.motionDidCancelAnimatingFrom?(viewController: fvc)
$0.motionDidCancelTransition?() $0.motionDidCancelTransition?()
} }
} }
tContext?.cancelInteractiveTransition() tContext?.cancelInteractiveTransition()
} }
tContext?.completeTransition(finished) tContext?.completeTransition(finished)
} }
} }
// custom transition helper, used in motion_replaceViewController fileprivate extension Motion {
/// Prepares the from and to view controllers.
func prepareViewControllers() {
guard let fvc = fromViewController, let tvc = toViewController else {
return
}
processForMotionDelegate(viewController: fvc) {
$0.motionWillStartTransition?()
$0.motionWillStartAnimatingTo?(viewController: tvc)
}
processForMotionDelegate(viewController: tvc) {
$0.motionWillStartTransition?()
$0.motionWillStartAnimatingFrom?(viewController: fvc)
}
}
/// Prepares the snapshot view, which hides any flashing that may occur.
func prepareSnapshotView() {
fullScreenSnapshot = transitionContainer.window?.snapshotView(afterScreenUpdates: true) ?? fromView.snapshotView(afterScreenUpdates: true)
(transitionContainer.window ?? transitionContainer)?.addSubview(fullScreenSnapshot)
if let v = fromViewController?.motionStoredSnapshot {
v.removeFromSuperview()
fromViewController?.motionStoredSnapshot = nil
}
if let v = toViewController?.motionStoredSnapshot {
v.removeFromSuperview()
toViewController?.motionStoredSnapshot = nil
}
}
/// Prepares the MotionContext instance.
func prepareMotionContext() {
context.loadViewAlpha(rootView: toView)
context.loadViewAlpha(rootView: fromView)
container.addSubview(toView)
container.addSubview(fromView)
}
/// Prepares the toView instance.
func prepareToView() {
toView.frame = fromView.frame
toView.updateConstraints()
toView.setNeedsLayout()
toView.layoutIfNeeded()
}
/// Prepares the view hierarchy.
func prepareViewHierarchy() {
context.set(fromViews: fromView.flattenedViewHierarchy, toViews: toView.flattenedViewHierarchy)
}
}
internal extension Motion { internal extension Motion {
override func prepareForTransition() {
super.prepareForTransition()
insert(preprocessor: DefaultAnimationPreprocessor(motion: self), before: DurationPreprocessor.self)
}
}
internal extension Motion {
/**
A helper transition function.
- Parameter from: A UIViewController.
- Parameter to: A UIViewController.
- Parameter in view: A UIView.
- Parameter completion: An optional completion handler.
*/
func transition(from: UIViewController, to: UIViewController, in view: UIView, completion: ((Bool) -> Void)? = nil) { func transition(from: UIViewController, to: UIViewController, in view: UIView, completion: ((Bool) -> Void)? = nil) {
guard !isTransitioning else { return } guard !isTransitioning else {
presenting = true return
}
isPresenting = true
transitionContainer = view transitionContainer = view
fromViewController = from fromViewController = from
toViewController = to toViewController = to
completionCallback = completion completionCallback = completion
start() start()
} }
} }
// delegate helper
internal extension Motion { internal extension Motion {
func closureProcessForMotionDelegate<T: UIViewController>(vc: T, closure: (MotionViewControllerDelegate) -> Void) { /**
if let delegate = vc as? MotionViewControllerDelegate { Helper for processing the MotionViewControllerDelegate.
closure(delegate) - Parameter viewController: A UIViewController of type `T`.
- Parameter execute: A callback for execution during processing.
*/
func processForMotionDelegate<T: UIViewController>(viewController: T, execute: (MotionViewControllerDelegate) -> Void) {
if let delegate = viewController as? MotionViewControllerDelegate {
execute(delegate)
} }
if let navigationController = vc as? UINavigationController, if let v = viewController as? UINavigationController,
let delegate = navigationController.topViewController as? MotionViewControllerDelegate { let delegate = v.topViewController as? MotionViewControllerDelegate {
closure(delegate) execute(delegate)
} }
if let tabBarController = vc as? UITabBarController, if let v = viewController as? UITabBarController,
let delegate = tabBarController.viewControllers?[tabBarController.selectedIndex] as? MotionViewControllerDelegate { let delegate = v.viewControllers?[v.selectedIndex] as? MotionViewControllerDelegate {
closure(delegate) execute(delegate)
} }
} }
} }
...@@ -359,18 +444,18 @@ extension Motion: UIViewControllerAnimatedTransitioning { ...@@ -359,18 +444,18 @@ extension Motion: UIViewControllerAnimatedTransitioning {
extension Motion:UIViewControllerTransitioningDelegate { extension Motion:UIViewControllerTransitioningDelegate {
var interactiveTransitioning: UIViewControllerInteractiveTransitioning? { var interactiveTransitioning: UIViewControllerInteractiveTransitioning? {
return forceNotInteractive ? nil : self return forceNonInteractive ? nil : self
} }
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = true self.isPresenting = true
self.fromViewController = fromViewController ?? presenting self.fromViewController = fromViewController ?? presenting
self.toViewController = toViewController ?? presented self.toViewController = toViewController ?? presented
return self return self
} }
public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = false self.isPresenting = false
self.fromViewController = fromViewController ?? dismissed self.fromViewController = fromViewController ?? dismissed
return self return self
} }
...@@ -395,10 +480,10 @@ extension Motion: UIViewControllerInteractiveTransitioning { ...@@ -395,10 +480,10 @@ extension Motion: UIViewControllerInteractiveTransitioning {
extension Motion: UINavigationControllerDelegate { extension Motion: UINavigationControllerDelegate {
public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = operation == .push self.isPresenting = operation == .push
self.fromViewController = fromViewController ?? fromVC self.fromViewController = fromViewController ?? fromVC
self.toViewController = toViewController ?? toVC self.toViewController = toViewController ?? toVC
self.inNavigationController = true self.isNavigationController = true
return self return self
} }
...@@ -420,10 +505,10 @@ extension Motion: UITabBarControllerDelegate { ...@@ -420,10 +505,10 @@ extension Motion: UITabBarControllerDelegate {
isAnimating = true isAnimating = true
let fromVCIndex = tabBarController.childViewControllers.index(of: fromVC)! let fromVCIndex = tabBarController.childViewControllers.index(of: fromVC)!
let toVCIndex = tabBarController.childViewControllers.index(of: toVC)! let toVCIndex = tabBarController.childViewControllers.index(of: toVC)!
self.presenting = toVCIndex > fromVCIndex self.isPresenting = toVCIndex > fromVCIndex
self.fromViewController = fromViewController ?? fromVC self.fromViewController = fromViewController ?? fromVC
self.toViewController = toViewController ?? toVC self.toViewController = toViewController ?? toVC
self.inTabBarController = true self.isTabBarController = true
return self return self
} }
} }
......
...@@ -56,8 +56,8 @@ public class MotionContext { ...@@ -56,8 +56,8 @@ public class MotionContext {
if let motionIdentifier = view.motionIdentifier { if let motionIdentifier = view.motionIdentifier {
idMap[motionIdentifier] = view idMap[motionIdentifier] = view
} }
if let modifiers = view.motionTransitions { if let transitions = view.motionTransitions {
targetStates[view] = MotionTargetState(modifiers: modifiers) targetStates[view] = MotionTargetState(transitions: transitions)
} }
} }
} }
......
...@@ -195,9 +195,9 @@ public extension MotionController { ...@@ -195,9 +195,9 @@ public extension MotionController {
- modifiers: the modifiers to override - modifiers: the modifiers to override
- view: the view to override to - view: the view to override to
*/ */
public func apply(modifiers: [MotionTransition], to view: UIView) { public func apply(transitions: [MotionTransition], to view: UIView) {
guard isTransitioning else { return } guard isTransitioning else { return }
let targetState = MotionTargetState(modifiers: modifiers) let targetState = MotionTargetState(transitions: transitions)
if let otherView = self.context.pairedView(for: view) { if let otherView = self.context.pairedView(for: view) {
for animator in self.animators { for animator in self.animators {
animator.apply(state: targetState, to: otherView) animator.apply(state: targetState, to: otherView)
...@@ -272,6 +272,8 @@ internal extension MotionController { ...@@ -272,6 +272,8 @@ internal extension MotionController {
} }
} }
func processContext() { func processContext() {
guard isTransitioning else { fatalError() } guard isTransitioning else { fatalError() }
for processor in processors { for processor in processors {
......
...@@ -105,16 +105,16 @@ public struct MotionTargetState { ...@@ -105,16 +105,16 @@ public struct MotionTargetState {
public var forceAnimate: Bool = false public var forceAnimate: Bool = false
public var custom: [String:Any]? public var custom: [String:Any]?
init(modifiers: [MotionTransition]) { init(transitions: [MotionTransition]) {
append(contentsOf: modifiers) append(contentsOf: transitions)
} }
public mutating func append(_ modifier: MotionTransition) { public mutating func append(_ transition: MotionTransition) {
modifier.apply(&self) transition.apply(&self)
} }
public mutating func append(contentsOf modifiers: [MotionTransition]) { public mutating func append(contentsOf transitions: [MotionTransition]) {
for modifier in modifiers { for modifier in transitions {
modifier.apply(&self) modifier.apply(&self)
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment