Commit 19664a2f by Daniel Dahan

partial work completed for reworking Motion and MotionController

parent baf1bf57
......@@ -198,8 +198,8 @@
96AEB6691EE4610F009A3BE0 /* Debug Plugin */,
96AEB66D1EE4610F009A3BE0 /* Extensions */,
96AEB6771EE4610F009A3BE0 /* Motion.swift */,
963150D41EE51C7A002B0D42 /* MotionAnimation.swift */,
96AEB6781EE4610F009A3BE0 /* MotionController.swift */,
963150D41EE51C7A002B0D42 /* MotionAnimation.swift */,
96AEB6791EE4610F009A3BE0 /* MotionContext.swift */,
96AEB67A1EE4610F009A3BE0 /* MotionIndependentController.swift */,
96AEB67B1EE4610F009A3BE0 /* MotionTransition.swift */,
......
......@@ -410,6 +410,11 @@ extension MotionCoreAnimationViewContext {
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) {
let timeOffset = elapsedTime - targetState.delay
for (key, anim) in layer.animations {
......
......@@ -38,13 +38,13 @@ public class MotionDebugPlugin: MotionPlugin {
var updating = false
override public func animate(fromViews: [UIView], toViews: [UIView]) -> TimeInterval {
if Motion.shared.forceNotInteractive { return 0 }
if Motion.shared.forceNonInteractive { return 0 }
var hasArc = false
for v in context.fromViews + context.toViews where context[v]?.arc != nil && context[v]?.position != nil {
hasArc = true
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.delegate = self
UIApplication.shared.keyWindow!.addSubview(debugView)
......@@ -81,7 +81,7 @@ public class MotionDebugPlugin: MotionPlugin {
extension MotionDebugPlugin:MotionDebugViewDelegate {
public func onDone() {
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 {
Motion.shared.end()
} else {
......@@ -90,7 +90,7 @@ extension MotionDebugPlugin:MotionDebugViewDelegate {
}
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))
}
......
......@@ -235,11 +235,11 @@ class DefaultAnimationPreprocessor: BasePreprocessor {
override func process(fromViews: [UIView], toViews: [UIView]) {
guard let motion = motion else { return }
var defaultAnimation = motion.defaultAnimation
let inNavigationController = motion.inNavigationController
let inTabBarController = motion.inTabBarController
let inNavigationController = motion.isNavigationController
let inTabBarController = motion.isTabBarController
let toViewController = motion.toViewController
let fromViewController = motion.fromViewController
let presenting = motion.presenting
let presenting = motion.isPresenting
let fromOverFullScreen = motion.fromOverFullScreen
let toOverFullScreen = motion.toOverFullScreen
let toView = motion.toView
......
......@@ -312,6 +312,7 @@ extension UIViewController {
/**
Replace the current view controller with another view controller on the
navigation/modal stack.
- Parameter with next: A UIViewController.
*/
public func motion_replaceViewController(with next: UIViewController) {
guard !Motion.shared.isTransitioning else {
......@@ -328,7 +329,7 @@ extension UIViewController {
}
if navigationController.isMotionEnabled {
Motion.shared.forceNotInteractive = true
Motion.shared.forceNonInteractive = true
}
navigationController.setViewControllers(v, animated: true)
......
......@@ -41,296 +41,381 @@ import UIKit
func update(progress:Double)
func end()
func cancel()
func apply(modifiers:[MotionTransition], to view:UIView)
func apply(transitions: [MotionTransition], to view: UIView)
```
*/
public class Motion: MotionController {
// MARK: Shared Access
/// Shared singleton object for controlling the transition
public static let shared = Motion()
// MARK: Properties
/// destination view controller
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
public override var progress: Double {
didSet {
if isTransitioning {
transitionContext?.updateInteractiveTransition(CGFloat(progress))
}
}
}
public var isAnimating: Bool = false
/// a UIViewControllerContextTransitioning object provided by UIKit,
/// might be nil when isTransitioning. This happens when calling motionReplaceViewController
internal weak var transitionContext: UIViewControllerContextTransitioning?
internal var fullScreenSnapshot: UIView!
internal var defaultAnimation: MotionDefaultAnimationType = .auto
internal var containerColor: UIColor?
// 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 transition
internal var forceNotInteractive = false
internal var insertToViewFirst = false
internal var inNavigationController = false
internal var inTabBarController = false
internal var inContainerController: Bool {
return inNavigationController || inTabBarController
}
internal var toOverFullScreen: Bool {
return !inContainerController && (toViewController!.modalPresentationStyle == .overFullScreen || toViewController!.modalPresentationStyle == .overCurrentContext)
}
internal var fromOverFullScreen: Bool {
return !inContainerController && (fromViewController!.modalPresentationStyle == .overFullScreen || fromViewController!.modalPresentationStyle == .overCurrentContext)
}
/// Shared singleton object for controlling the transition
public static let shared = Motion()
internal var toView: UIView { return toViewController!.view }
internal var fromView: UIView { return fromViewController!.view }
/// Source view controller.
public internal(set) var fromViewController: UIViewController?
internal override init() { super.init() }
}
/// Destination view controller.
public internal(set) var toViewController: UIViewController?
/// 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 {
didSet {
if isTransitioning {
transitionContext?.updateInteractiveTransition(CGFloat(progress))
}
}
}
public extension Motion {
/// Indicates whether the transition is animating or not.
public var isAnimating = false
/**
A UIViewControllerContextTransitioning object provided by UIKit, which
might be nil when isTransitioning. This happens when calling motion_replaceViewController
*/
internal weak var transitionContext: UIViewControllerContextTransitioning?
/// Turn off built-in animation for next transition
func disableDefaultAnimationForNextTransition() {
defaultAnimation = .none
}
/// A reference to a fullscreen snapshot.
internal var fullScreenSnapshot: UIView!
/// Set the default animation for next transition
/// This usually overrides rootView's motionTransitions during the transition
///
/// - Parameter animation: animation type
func setDefaultAnimationForNextTransition(_ animation: MotionDefaultAnimationType) {
defaultAnimation = animation
}
/// Default animation type.
internal var defaultAnimation = MotionDefaultAnimationType.auto
/// Set the container color for next transition
///
/// - Parameter color: container color
func setContainerColorForNextTransition(_ color: UIColor?) {
containerColor = color
}
}
/// The color of the transitioning container.
internal var containerBackgroundColor: UIColor?
/**
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
// internal methods for transition
internal extension Motion {
func start() {
guard isTransitioning else { return }
if let fvc = fromViewController, let tvc = toViewController {
closureProcessForMotionDelegate(vc: fvc) {
$0.motionWillStartTransition?()
$0.motionWillStartAnimatingTo?(viewController: tvc)
}
closureProcessForMotionDelegate(vc: tvc) {
$0.motionWillStartTransition?()
$0.motionWillStartAnimatingFrom?(viewController: fvc)
}
/// Inserts the to-views first.
internal var insertToViewFirst = false
/// Indicates whether a UINavigationController is transitioning.
internal var isNavigationController = false
/// 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
}
// 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
/// Indicates whether the from view controller is full screen.
internal var fromOverFullScreen: Bool {
return !isContainerController && (.overFullScreen == fromViewController!.modalPresentationStyle || .overCurrentContext == fromViewController!.modalPresentationStyle)
}
if let oldSnapshot = toViewController?.motionStoredSnapshot {
oldSnapshot.removeFromSuperview()
toViewController?.motionStoredSnapshot = nil
/// Indicates whether the to view controller is full screen.
internal var toOverFullScreen: Bool {
return !isContainerController && (.overFullScreen == toViewController!.modalPresentationStyle || .overCurrentContext == toViewController!.modalPresentationStyle)
}
prepareForTransition()
insert(preprocessor: DefaultAnimationPreprocessor(motion: self), before: DurationPreprocessor.self)
context.loadViewAlpha(rootView: toView)
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()
prepareForAnimation()
context.hide(view: toView)
#if os(tvOS)
animate()
#else
if inNavigationController {
// When animating within navigationController, we have to dispatch later into the main queue.
// otherwise snapshots will be pure white. Possibly a bug with UIKit
DispatchQueue.main.async {
self.animate()
}
} else {
animate()
}
#endif
}
override func animate() {
context.unhide(view: toView)
/// A reference to the from-view, fromViewController.view.
internal var fromView: UIView {
return fromViewController!.view
}
/// A reference to the to-view, toViewController.view.
internal var toView: UIView {
return toViewController!.view
}
if let containerColor = containerColor {
container.backgroundColor = containerColor
} else if !toOverFullScreen && !fromOverFullScreen {
container.backgroundColor = toView.backgroundColor
/// An initializer.
internal override init() {
super.init()
}
}
if fromOverFullScreen {
insertToViewFirst = true
public extension Motion {
/// Turn off built-in animations for the next transition.
func disableDefaultAnimationForNextTransition() {
defaultAnimation = .none
}
for animator in animators {
if let animator = animator as? MotionHasInsertOrder {
animator.insertToViewFirst = insertToViewFirst
}
/**
Set the default animation for the next transition. This may override the
root-view's motionTransitions during the transition.
- Parameter animation: A MotionDefaultAnimationType.
*/
func setDefaultAnimationForNextTransition(_ animation: MotionDefaultAnimationType) {
defaultAnimation = animation
}
super.animate()
fullScreenSnapshot!.removeFromSuperview()
}
override func complete(finished: Bool) {
guard isTransitioning else { return }
context.clean()
if finished && presenting && toOverFullScreen {
// finished presenting a overFullScreen VC
context.unhide(rootView: toView)
context.removeSnapshots(rootView: toView)
context.storeViewAlpha(rootView: fromView)
fromViewController!.motionStoredSnapshot = container
fromView.removeFromSuperview()
fromView.addSubview(container)
} else if !finished && !presenting && fromOverFullScreen {
// cancelled dismissing a overFullScreen VC
context.unhide(rootView: fromView)
context.removeSnapshots(rootView: fromView)
context.storeViewAlpha(rootView: toView)
toViewController!.motionStoredSnapshot = container
toView.removeFromSuperview()
toView.addSubview(container)
} else {
context.unhideAll()
context.removeAllSnapshots()
container.removeFromSuperview()
/**
Set the container background color for the next transition.
- Parameter _ color: An optional UIColor.
*/
func setContainerBackgroundColorForNextTransition(_ color: UIColor?) {
containerBackgroundColor = color
}
}
// move fromView & toView back from our container back to the one supplied by UIKit
if (toOverFullScreen && finished) || (fromOverFullScreen && !finished) {
transitionContainer.addSubview(finished ? fromView : toView)
internal extension Motion {
/// Starts the transition animation.
func start() {
guard isTransitioning else {
return
}
prepareViewControllers()
prepareSnapshotView()
prepareForTransition()
prepareMotionContext()
prepareToView()
prepareViewHierarchy()
processContext()
prepareForAnimation()
context.hide(view: toView)
#if os(tvOS)
animate()
#else
if isNavigationController {
// When animating within navigationController, we have to dispatch later into the main queue.
// otherwise snapshots will be pure white. Possibly a bug with UIKit
DispatchQueue.main.async { [weak self] in
self?.animate()
}
} else {
animate()
}
#endif
}
transitionContainer.addSubview(finished ? toView : fromView)
if presenting != finished, !inContainerController {
// only happens when present a .overFullScreen VC
// bug: http://openradar.appspot.com/radar?id=5320103646199808
UIApplication.shared.keyWindow!.addSubview(presenting ? fromView : toView)
override func animate() {
context.unhide(view: toView)
if let containerBackgroundColor = containerBackgroundColor {
container.backgroundColor = containerBackgroundColor
} else if !toOverFullScreen && !fromOverFullScreen {
container.backgroundColor = toView.backgroundColor
}
if fromOverFullScreen {
insertToViewFirst = true
}
for animator in animators {
if let animator = animator as? MotionHasInsertOrder {
animator.insertToViewFirst = insertToViewFirst
}
}
super.animate()
fullScreenSnapshot!.removeFromSuperview()
}
// use temp variables to remember these values
// because we have to reset everything before calling
// any delegate or completion block
let tContext = transitionContext
let fvc = fromViewController
let tvc = toViewController
transitionContext = nil
fromViewController = nil
toViewController = nil
containerColor = nil
inNavigationController = false
inTabBarController = false
forceNotInteractive = false
insertToViewFirst = false
defaultAnimation = .auto
super.complete(finished: finished)
if finished {
if let fvc = fvc, let tvc = tvc {
closureProcessForMotionDelegate(vc: fvc) {
$0.motionDidEndAnimatingTo?(viewController: tvc)
$0.motionDidEndTransition?()
override func complete(finished: Bool) {
guard isTransitioning else {
return
}
closureProcessForMotionDelegate(vc: tvc) {
$0.motionDidEndAnimatingFrom?(viewController: fvc)
$0.motionDidEndTransition?()
context.clean()
if finished && isPresenting && toOverFullScreen {
// finished presenting a overFullScreen VC
context.unhide(rootView: toView)
context.removeSnapshots(rootView: toView)
context.storeViewAlpha(rootView: fromView)
fromViewController!.motionStoredSnapshot = container
fromView.removeFromSuperview()
fromView.addSubview(container)
} else if !finished && !isPresenting && fromOverFullScreen {
// cancelled dismissing a overFullScreen VC
context.unhide(rootView: fromView)
context.removeSnapshots(rootView: fromView)
context.storeViewAlpha(rootView: toView)
toViewController!.motionStoredSnapshot = container
toView.removeFromSuperview()
toView.addSubview(container)
} else {
context.unhideAll()
context.removeAllSnapshots()
container.removeFromSuperview()
}
// move fromView & toView back from our container back to the one supplied by UIKit
if (toOverFullScreen && finished) || (fromOverFullScreen && !finished) {
transitionContainer.addSubview(finished ? fromView : toView)
}
}
tContext?.finishInteractiveTransition()
} else {
if let fvc = fvc, let tvc = tvc {
closureProcessForMotionDelegate(vc: fvc) {
$0.motionDidCancelAnimatingTo?(viewController: tvc)
$0.motionDidCancelTransition?()
transitionContainer.addSubview(finished ? toView : fromView)
if isPresenting != finished, !isContainerController {
// only happens when present a .overFullScreen VC
// bug: http://openradar.appspot.com/radar?id=5320103646199808
UIApplication.shared.keyWindow!.addSubview(isPresenting ? fromView : toView)
}
closureProcessForMotionDelegate(vc: tvc) {
$0.motionDidCancelAnimatingFrom?(viewController: fvc)
$0.motionDidCancelTransition?()
// use temp variables to remember these values
// because we have to reset everything before calling
// any delegate or completion block
let tContext = transitionContext
let fvc = fromViewController
let tvc = toViewController
transitionContext = nil
fromViewController = nil
toViewController = nil
containerBackgroundColor = nil
isNavigationController = false
isTabBarController = false
forceNonInteractive = false
insertToViewFirst = false
defaultAnimation = .auto
super.complete(finished: finished)
if finished {
if let fvc = fvc, let tvc = tvc {
processForMotionDelegate(viewController: fvc) {
$0.motionDidEndAnimatingTo?(viewController: tvc)
$0.motionDidEndTransition?()
}
processForMotionDelegate(viewController: tvc) {
$0.motionDidEndAnimatingFrom?(viewController: fvc)
$0.motionDidEndTransition?()
}
}
tContext?.finishInteractiveTransition()
} else {
if let fvc = fvc, let tvc = tvc {
processForMotionDelegate(viewController: fvc) {
$0.motionDidCancelAnimatingTo?(viewController: tvc)
$0.motionDidCancelTransition?()
}
processForMotionDelegate(viewController: tvc) {
$0.motionDidCancelAnimatingFrom?(viewController: fvc)
$0.motionDidCancelTransition?()
}
}
tContext?.cancelInteractiveTransition()
}
}
tContext?.cancelInteractiveTransition()
tContext?.completeTransition(finished)
}
tContext?.completeTransition(finished)
}
}
// custom transition helper, used in motion_replaceViewController
internal extension Motion {
func transition(from: UIViewController, to: UIViewController, in view: UIView, completion: ((Bool) -> Void)? = nil) {
guard !isTransitioning else { return }
presenting = true
transitionContainer = view
fromViewController = from
toViewController = to
completionCallback = completion
start()
}
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)
}
}
// delegate helper
internal extension Motion {
func closureProcessForMotionDelegate<T: UIViewController>(vc: T, closure: (MotionViewControllerDelegate) -> Void) {
if let delegate = vc as? MotionViewControllerDelegate {
closure(delegate)
override func prepareForTransition() {
super.prepareForTransition()
insert(preprocessor: DefaultAnimationPreprocessor(motion: self), before: DurationPreprocessor.self)
}
}
if let navigationController = vc as? UINavigationController,
let delegate = navigationController.topViewController as? MotionViewControllerDelegate {
closure(delegate)
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) {
guard !isTransitioning else {
return
}
isPresenting = true
transitionContainer = view
fromViewController = from
toViewController = to
completionCallback = completion
start()
}
}
if let tabBarController = vc as? UITabBarController,
let delegate = tabBarController.viewControllers?[tabBarController.selectedIndex] as? MotionViewControllerDelegate {
closure(delegate)
internal extension Motion {
/**
Helper for processing the MotionViewControllerDelegate.
- 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 v = viewController as? UINavigationController,
let delegate = v.topViewController as? MotionViewControllerDelegate {
execute(delegate)
}
if let v = viewController as? UITabBarController,
let delegate = v.viewControllers?[v.selectedIndex] as? MotionViewControllerDelegate {
execute(delegate)
}
}
}
}
// MARK: UIKit Protocol Conformance
......@@ -359,18 +444,18 @@ extension Motion: UIViewControllerAnimatedTransitioning {
extension Motion:UIViewControllerTransitioningDelegate {
var interactiveTransitioning: UIViewControllerInteractiveTransitioning? {
return forceNotInteractive ? nil : self
return forceNonInteractive ? nil : self
}
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = true
self.isPresenting = true
self.fromViewController = fromViewController ?? presenting
self.toViewController = toViewController ?? presented
return self
}
public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = false
self.isPresenting = false
self.fromViewController = fromViewController ?? dismissed
return self
}
......@@ -395,10 +480,10 @@ extension Motion: UIViewControllerInteractiveTransitioning {
extension Motion: UINavigationControllerDelegate {
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.toViewController = toViewController ?? toVC
self.inNavigationController = true
self.isNavigationController = true
return self
}
......@@ -420,10 +505,10 @@ extension Motion: UITabBarControllerDelegate {
isAnimating = true
let fromVCIndex = tabBarController.childViewControllers.index(of: fromVC)!
let toVCIndex = tabBarController.childViewControllers.index(of: toVC)!
self.presenting = toVCIndex > fromVCIndex
self.isPresenting = toVCIndex > fromVCIndex
self.fromViewController = fromViewController ?? fromVC
self.toViewController = toViewController ?? toVC
self.inTabBarController = true
self.isTabBarController = true
return self
}
}
......
......@@ -56,8 +56,8 @@ public class MotionContext {
if let motionIdentifier = view.motionIdentifier {
idMap[motionIdentifier] = view
}
if let modifiers = view.motionTransitions {
targetStates[view] = MotionTargetState(modifiers: modifiers)
if let transitions = view.motionTransitions {
targetStates[view] = MotionTargetState(transitions: transitions)
}
}
}
......
......@@ -195,9 +195,9 @@ public extension MotionController {
- modifiers: the modifiers to override
- 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 }
let targetState = MotionTargetState(modifiers: modifiers)
let targetState = MotionTargetState(transitions: transitions)
if let otherView = self.context.pairedView(for: view) {
for animator in self.animators {
animator.apply(state: targetState, to: otherView)
......@@ -272,6 +272,8 @@ internal extension MotionController {
}
}
func processContext() {
guard isTransitioning else { fatalError() }
for processor in processors {
......
......@@ -105,16 +105,16 @@ public struct MotionTargetState {
public var forceAnimate: Bool = false
public var custom: [String:Any]?
init(modifiers: [MotionTransition]) {
append(contentsOf: modifiers)
init(transitions: [MotionTransition]) {
append(contentsOf: transitions)
}
public mutating func append(_ modifier: MotionTransition) {
modifier.apply(&self)
public mutating func append(_ transition: MotionTransition) {
transition.apply(&self)
}
public mutating func append(contentsOf modifiers: [MotionTransition]) {
for modifier in modifiers {
public mutating func append(contentsOf transitions: [MotionTransition]) {
for modifier in transitions {
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