Commit baf1bf57 by Daniel Dahan

reworked Motion+UIViewController

parent 53088a53
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
963150D11EE50DA6002B0D42 /* Motion+Obj-C.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Motion+Obj-C.swift"; sourceTree = "<group>"; }; 963150D11EE50DA6002B0D42 /* Motion+Obj-C.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Motion+Obj-C.swift"; sourceTree = "<group>"; };
963150D41EE51C7A002B0D42 /* MotionAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimation.swift; sourceTree = "<group>"; }; 963150D41EE51C7A002B0D42 /* MotionAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimation.swift; sourceTree = "<group>"; };
963150D91EE51EB4002B0D42 /* MotionAnimationFillMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimationFillMode.swift; sourceTree = "<group>"; }; 963150D91EE51EB4002B0D42 /* MotionAnimationFillMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionAnimationFillMode.swift; path = ../Extensions/MotionAnimationFillMode.swift; sourceTree = "<group>"; };
968989B81EE5B34B003B8F3D /* MotionHasInsertOrder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionHasInsertOrder.swift; sourceTree = "<group>"; }; 968989B81EE5B34B003B8F3D /* MotionHasInsertOrder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionHasInsertOrder.swift; sourceTree = "<group>"; };
968989DB1EE65F2B003B8F3D /* MotionPreprocessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionPreprocessor.swift; sourceTree = "<group>"; }; 968989DB1EE65F2B003B8F3D /* MotionPreprocessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionPreprocessor.swift; sourceTree = "<group>"; };
968989DD1EE6633E003B8F3D /* MotionAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimator.swift; sourceTree = "<group>"; }; 968989DD1EE6633E003B8F3D /* MotionAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimator.swift; sourceTree = "<group>"; };
...@@ -117,6 +117,7 @@ ...@@ -117,6 +117,7 @@
96AEB6671EE4610F009A3BE0 /* MotionDefaultAnimator.swift */, 96AEB6671EE4610F009A3BE0 /* MotionDefaultAnimator.swift */,
96AEB6681EE4610F009A3BE0 /* MotionViewPropertyViewContext.swift */, 96AEB6681EE4610F009A3BE0 /* MotionViewPropertyViewContext.swift */,
968989B81EE5B34B003B8F3D /* MotionHasInsertOrder.swift */, 968989B81EE5B34B003B8F3D /* MotionHasInsertOrder.swift */,
963150D91EE51EB4002B0D42 /* MotionAnimationFillMode.swift */,
); );
path = Animator; path = Animator;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -141,7 +142,6 @@ ...@@ -141,7 +142,6 @@
96AEB6731EE4610F009A3BE0 /* Motion+UIKit.swift */, 96AEB6731EE4610F009A3BE0 /* Motion+UIKit.swift */,
96AEB6741EE4610F009A3BE0 /* Motion+UIView.swift */, 96AEB6741EE4610F009A3BE0 /* Motion+UIView.swift */,
96AEB6751EE4610F009A3BE0 /* Motion+UIViewController.swift */, 96AEB6751EE4610F009A3BE0 /* Motion+UIViewController.swift */,
963150D91EE51EB4002B0D42 /* MotionAnimationFillMode.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
......
...@@ -49,9 +49,9 @@ internal extension UIView { ...@@ -49,9 +49,9 @@ internal extension UIView {
} }
} }
fileprivate var MotionInstanceKey: UInt8 = 0 fileprivate var AssociatedInstanceKey: UInt8 = 0
fileprivate struct MotionInstance { fileprivate struct AssociatedInstance {
/// A boolean indicating whether Motion is enabled. /// A boolean indicating whether Motion is enabled.
fileprivate var isEnabled: Bool fileprivate var isEnabled: Bool
...@@ -69,15 +69,15 @@ fileprivate struct MotionInstance { ...@@ -69,15 +69,15 @@ fileprivate struct MotionInstance {
} }
extension UIView { extension UIView {
/// MotionInstance reference. /// AssociatedInstance reference.
fileprivate var motionInstance: MotionInstance { fileprivate var associatedInstance: AssociatedInstance {
get { get {
return AssociatedObject.get(base: self, key: &MotionInstanceKey) { return AssociatedObject.get(base: self, key: &AssociatedInstanceKey) {
return MotionInstance(isEnabled: true, identifier: nil, animations: nil, transitions: nil, alpha: 1) return AssociatedInstance(isEnabled: true, identifier: nil, animations: nil, transitions: nil, alpha: 1)
} }
} }
set(value) { set(value) {
AssociatedObject.set(base: self, key: &MotionInstanceKey, value: value) AssociatedObject.set(base: self, key: &AssociatedInstanceKey, value: value)
} }
} }
...@@ -85,10 +85,10 @@ extension UIView { ...@@ -85,10 +85,10 @@ extension UIView {
@IBInspectable @IBInspectable
public var isMotionEnabled: Bool { public var isMotionEnabled: Bool {
get { get {
return motionInstance.isEnabled return associatedInstance.isEnabled
} }
set(value) { set(value) {
motionInstance.isEnabled = value associatedInstance.isEnabled = value
} }
} }
...@@ -96,30 +96,30 @@ extension UIView { ...@@ -96,30 +96,30 @@ extension UIView {
@IBInspectable @IBInspectable
open var motionIdentifier: String? { open var motionIdentifier: String? {
get { get {
return motionInstance.identifier return associatedInstance.identifier
} }
set(value) { set(value) {
motionInstance.identifier = value associatedInstance.identifier = value
} }
} }
/// The animations to run. /// The animations to run.
open var motionAnimations: [MotionAnimation]? { open var motionAnimations: [MotionAnimation]? {
get { get {
return motionInstance.animations return associatedInstance.animations
} }
set(value) { set(value) {
motionInstance.animations = value associatedInstance.animations = value
} }
} }
/// The animations to run while in transition. /// The animations to run while in transition.
open var motionTransitions: [MotionTransition]? { open var motionTransitions: [MotionTransition]? {
get { get {
return motionInstance.transitions return associatedInstance.transitions
} }
set(value) { set(value) {
motionInstance.transitions = value associatedInstance.transitions = value
} }
} }
...@@ -127,10 +127,10 @@ extension UIView { ...@@ -127,10 +127,10 @@ extension UIView {
@IBInspectable @IBInspectable
open var motionAlpha: CGFloat? { open var motionAlpha: CGFloat? {
get { get {
return motionInstance.alpha return associatedInstance.alpha
} }
set(value) { set(value) {
motionInstance.alpha = value associatedInstance.alpha = value
} }
} }
} }
......
...@@ -28,84 +28,140 @@ ...@@ -28,84 +28,140 @@
import UIKit import UIKit
internal class MotionViewControllerConfig: NSObject { fileprivate var AssociatedInstanceKey: UInt8 = 0
var modalAnimation: MotionDefaultAnimationType = .auto
var navigationAnimation: MotionDefaultAnimationType = .auto
var tabBarAnimation: MotionDefaultAnimationType = .auto
fileprivate struct AssociatedInstance {
/// A reference to the modal animation.
var modalAnimationType: MotionDefaultAnimationType
/// A reference to the navigation animation.
var navigationAnimationType: MotionDefaultAnimationType
/// A reference to the tabBar animation.
var tabBarAnimationType: MotionDefaultAnimationType
/// A reference to the stored snapshot.
var storedSnapshot: UIView? var storedSnapshot: UIView?
/**
A reference to the previous navigation controller delegate
before Motion was enabled.
*/
var previousNavigationDelegate: UINavigationControllerDelegate? var previousNavigationDelegate: UINavigationControllerDelegate?
/**
A reference to the previous tab bar controller delegate
before Motion was enabled.
*/
var previousTabBarDelegate: UITabBarControllerDelegate? var previousTabBarDelegate: UITabBarControllerDelegate?
} }
public extension UIViewController { extension UIViewController {
private struct AssociatedKeys { /// AssociatedInstance reference.
static var motionConfig = "motionConfig" fileprivate var associatedInstance: AssociatedInstance {
get {
return AssociatedObject.get(base: self, key: &AssociatedInstanceKey) {
return AssociatedInstance(modalAnimationType: .auto,
navigationAnimationType: .auto,
tabBarAnimationType: .auto,
storedSnapshot: nil,
previousNavigationDelegate: nil,
previousTabBarDelegate: nil)
}
}
set(value) {
AssociatedObject.set(base: self, key: &AssociatedInstanceKey, value: value)
}
} }
internal var motionConfig: MotionViewControllerConfig { /// default motion animation type for presenting & dismissing modally
public var motionModalAnimationType: MotionDefaultAnimationType {
get { get {
if let config = objc_getAssociatedObject(self, &AssociatedKeys.motionConfig) as? MotionViewControllerConfig { return associatedInstance.modalAnimationType
return config
} }
let config = MotionViewControllerConfig() set(value) {
self.motionConfig = config associatedInstance.modalAnimationType = value
return config
} }
set { objc_setAssociatedObject(self, &AssociatedKeys.motionConfig, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
} }
internal var previousNavigationDelegate: UINavigationControllerDelegate? { @IBInspectable
get { return motionConfig.previousNavigationDelegate } public var motionModalAnimationTypeString: String? {
set { motionConfig.previousNavigationDelegate = newValue } get {
return associatedInstance.modalAnimationType.label
}
set(value) {
associatedInstance.modalAnimationType = value?.parseOne() ?? .auto
} }
internal var previousTabBarDelegate: UITabBarControllerDelegate? {
get { return motionConfig.previousTabBarDelegate }
set { motionConfig.previousTabBarDelegate = newValue }
} }
/// used for .overFullScreen presentation /// used for .overFullScreen presentation
internal var motionStoredSnapshot: UIView? { internal var motionStoredSnapshot: UIView? {
get { return motionConfig.storedSnapshot } get {
set { motionConfig.storedSnapshot = newValue } return associatedInstance.storedSnapshot
}
set(value) {
associatedInstance.storedSnapshot = value
}
} }
/// default motion animation type for presenting & dismissing modally /**
public var motionModalAnimationType: MotionDefaultAnimationType { A reference to the previous navigation controller delegate
get { return motionConfig.modalAnimation } before Motion was enabled.
set { motionConfig.modalAnimation = newValue } */
internal var previousNavigationDelegate: UINavigationControllerDelegate? {
get {
return associatedInstance.previousNavigationDelegate
}
set(value) {
associatedInstance.previousNavigationDelegate = value
}
} }
@IBInspectable public var motionModalAnimationTypeString: String? { /**
get { return motionConfig.modalAnimation.label } A reference to the previous tab bar controller delegate
set { motionConfig.modalAnimation = newValue?.parseOne() ?? .auto } before Motion was enabled.
*/
internal var previousTabBarDelegate: UITabBarControllerDelegate? {
get {
return associatedInstance.previousTabBarDelegate
}
set(value) {
associatedInstance.previousTabBarDelegate = value
}
} }
@IBInspectable public var isMotionEnabled: Bool { ///A boolean that indicates whether Motion is enabled or disabled.
@IBInspectable
public var isMotionEnabled: Bool {
get { get {
return transitioningDelegate is Motion return transitioningDelegate is Motion
} }
set(value) {
guard value != isMotionEnabled else {
return
}
set { if value {
guard newValue != isMotionEnabled else { return }
if newValue {
transitioningDelegate = Motion.shared transitioningDelegate = Motion.shared
if let navi = self as? UINavigationController {
previousNavigationDelegate = navi.delegate if let v = self as? UINavigationController {
navi.delegate = Motion.shared previousNavigationDelegate = v.delegate
v.delegate = Motion.shared
} }
if let tab = self as? UITabBarController {
previousTabBarDelegate = tab.delegate if let v = self as? UITabBarController {
tab.delegate = Motion.shared previousTabBarDelegate = v.delegate
v.delegate = Motion.shared
} }
} else { } else {
transitioningDelegate = nil transitioningDelegate = nil
if let navi = self as? UINavigationController, navi.delegate is Motion {
navi.delegate = previousNavigationDelegate if let v = self as? UINavigationController, v.delegate is Motion {
v.delegate = previousNavigationDelegate
} }
if let tab = self as? UITabBarController, tab.delegate is Motion {
tab.delegate = previousTabBarDelegate if let v = self as? UITabBarController, v.delegate is Motion {
v.delegate = previousTabBarDelegate
} }
} }
} }
...@@ -113,47 +169,58 @@ public extension UIViewController { ...@@ -113,47 +169,58 @@ public extension UIViewController {
} }
extension UINavigationController { extension UINavigationController {
/// default motion animation type for push and pop within the navigation controller /// Default motion animation type for push and pop within the navigation controller.
public var motionNavigationAnimationType: MotionDefaultAnimationType { public var motionNavigationAnimationType: MotionDefaultAnimationType {
get { return motionConfig.navigationAnimation } get {
set { motionConfig.navigationAnimation = newValue } return associatedInstance.navigationAnimationType
}
set(value) {
associatedInstance.navigationAnimationType = value
}
} }
@IBInspectable public var motionNavigationAnimationTypeString: String? { /// A String representation for the motionNavigationAnimationType.
get { return motionConfig.navigationAnimation.label } @IBInspectable
set { motionConfig.navigationAnimation = newValue?.parseOne() ?? .auto } public var motionNavigationAnimationTypeString: String? {
get {
return associatedInstance.navigationAnimationType.label
}
set(value) {
associatedInstance.navigationAnimationType = value?.parseOne() ?? .auto
}
} }
} }
extension UITabBarController { extension UITabBarController {
/// default motion animation type for switching tabs within the tab bar controller /// Default motion animation type for switching tabs within the tab bar controller.
public var motionTabBarAnimationType: MotionDefaultAnimationType { public var motionTabBarAnimationType: MotionDefaultAnimationType {
get { return motionConfig.tabBarAnimation } get {
set { motionConfig.tabBarAnimation = newValue } return associatedInstance.tabBarAnimationType
} }
set(value) {
@IBInspectable public var motionTabBarAnimationTypeString: String? { associatedInstance.tabBarAnimationType = value
get { return motionConfig.tabBarAnimation.label }
set { motionConfig.tabBarAnimation = newValue?.parseOne() ?? .auto }
} }
}
extension UIViewController {
@available(*, deprecated: 0.1.4, message: "use motion_dismissViewController instead")
@IBAction public func ht_dismiss(_ sender: UIView) {
motion_dismissViewController()
} }
@available(*, deprecated: 0.1.4, message: "use motion_replaceViewController(with:) instead") /// A String representation for the motionTabBarAnimationTypeString.
public func motionReplaceViewController(with next: UIViewController) { @IBInspectable
motion_replaceViewController(with: next) public var motionTabBarAnimationTypeString: String? {
get {
return associatedInstance.tabBarAnimationType.label }
set(value) {
associatedInstance.tabBarAnimationType = value?.parseOne() ?? .auto
}
} }
}
extension UIViewController {
/** /**
Dismiss the current view controller with animation. Will perform a navigationController.popViewController Dismiss the current view controller with animation. Will perform a
if the current view controller is contained inside a navigationController navigationController.popViewController if the current view controller
is contained inside a navigationController
*/ */
@IBAction public func motion_dismissViewController() { @IBAction
public func motion_dismissViewController() {
if let navigationController = navigationController, navigationController.viewControllers.first != self { if let navigationController = navigationController, navigationController.viewControllers.first != self {
navigationController.popViewController(animated: true) navigationController.popViewController(animated: true)
} else { } else {
...@@ -161,114 +228,127 @@ extension UIViewController { ...@@ -161,114 +228,127 @@ extension UIViewController {
} }
} }
/** /// Unwind to the root view controller using Motion.
Unwind to the root view controller using Motion @IBAction
*/ public func motion_unwindToRootViewController() {
@IBAction public func motion_unwindToRootViewController() {
motion_unwindToViewController { $0.presentingViewController == nil } motion_unwindToViewController { $0.presentingViewController == nil }
} }
/** /// Unwind to a specific view controller using Motion.
Unwind to a specific view controller using Motion
*/
public func motion_unwindToViewController(_ toViewController: UIViewController) { public func motion_unwindToViewController(_ toViewController: UIViewController) {
motion_unwindToViewController { $0 == toViewController } motion_unwindToViewController { $0 == toViewController }
} }
/** /// Unwind to a view controller that responds to the given selector using Motion.
Unwind to a view controller that responds to the given selector using Motion
*/
public func motion_unwindToViewController(withSelector: Selector) { public func motion_unwindToViewController(withSelector: Selector) {
motion_unwindToViewController { $0.responds(to: withSelector) } motion_unwindToViewController { $0.responds(to: withSelector) }
} }
/** /// Unwind to a view controller with given class using Motion
Unwind to a view controller with given class using Motion
*/
public func motion_unwindToViewController(withClass: AnyClass) { public func motion_unwindToViewController(withClass: AnyClass) {
motion_unwindToViewController { $0.isKind(of: withClass) } motion_unwindToViewController { $0.isKind(of: withClass) }
} }
/** /// Unwind to a view controller that the matchBlock returns true on.
Unwind to a view controller that the matchBlock returns true on.
*/
public func motion_unwindToViewController(withMatchBlock: (UIViewController) -> Bool) { public func motion_unwindToViewController(withMatchBlock: (UIViewController) -> Bool) {
var target: UIViewController? = nil var target: UIViewController?
var current: UIViewController? = self var current: UIViewController? = self
while target == nil && current != nil { while nil == target && nil != current {
if let childViewControllers = (current as? UINavigationController)?.childViewControllers ?? current!.navigationController?.childViewControllers { if let childViewControllers = (current as? UINavigationController)?.childViewControllers ?? current!.navigationController?.childViewControllers {
for vc in childViewControllers.reversed() { for v in childViewControllers.reversed() {
if vc != self, withMatchBlock(vc) { if self != v, withMatchBlock(v) {
target = vc target = v
break break
} }
} }
} }
if target == nil {
current = current!.presentingViewController guard nil == target else {
if let vc = current, withMatchBlock(vc) == true { continue
target = vc }
current = current?.presentingViewController
guard let v = current, withMatchBlock(v) else {
continue
}
target = v
} }
guard let v = target else {
return
} }
guard nil != v.presentedViewController else {
v.navigationController?.popToViewController(v, animated: true)
return
} }
if let target = target { v.navigationController?.popToViewController(v, animated: false)
if target.presentedViewController != nil {
_ = target.navigationController?.popToViewController(target, animated: false)
let fromVC = self.navigationController ?? self let fromVC = self.navigationController ?? self
let toVC = target.navigationController ?? target let toVC = v.navigationController ?? v
if target.presentedViewController != fromVC { if v.presentedViewController != fromVC {
// UIKit's UIViewController.dismiss will jump to target.presentedViewController then perform the dismiss. /**
// We overcome this behavior by inserting a snapshot into target.presentedViewController UIKit's UIViewController.dismiss will jump to target.presentedViewController then perform the dismiss.
// And also force Motion to use the current VC as the fromViewController We overcome this behavior by inserting a snapshot into target.presentedViewController
And also force Motion to use the current view controller as the fromViewController.
*/
Motion.shared.fromViewController = fromVC Motion.shared.fromViewController = fromVC
let snapshotView = fromVC.view.snapshotView(afterScreenUpdates: true)!
toVC.presentedViewController!.view.addSubview(snapshotView)
}
toVC.dismiss(animated: true, completion: nil) guard let snapshot = fromVC.view.snapshotView(afterScreenUpdates: true) else {
} else { return
_ = target.navigationController?.popToViewController(target, animated: true)
} }
} else {
// unwind target not found toVC.presentedViewController?.view.addSubview(snapshot)
} }
toVC.dismiss(animated: true, completion: nil)
} }
/** /**
Replace the current view controller with another VC on the navigation/modal stack. Replace the current view controller with another view controller on the
navigation/modal stack.
*/ */
public func motion_replaceViewController(with next: UIViewController) { public func motion_replaceViewController(with next: UIViewController) {
if Motion.shared.transitioning { guard !Motion.shared.isTransitioning else {
print("motion_replaceViewController cancelled because Motion was doing a transition. Use Motion.shared.cancel(animated:false) or Motion.shared.end(animated:false) to stop the transition first before calling motion_replaceViewController.") print("motion_replaceViewController cancelled because Motion was doing a transition. Use Motion.shared.cancel(animated:false) or Motion.shared.end(animated:false) to stop the transition first before calling motion_replaceViewController.")
return return
} }
if let navigationController = navigationController { if let navigationController = navigationController {
var vcs = navigationController.childViewControllers var v = navigationController.childViewControllers
if !vcs.isEmpty {
vcs.removeLast() if !v.isEmpty {
vcs.append(next) v.removeLast()
v.append(next)
} }
if navigationController.isMotionEnabled { if navigationController.isMotionEnabled {
Motion.shared.forceNotInteractive = true Motion.shared.forceNotInteractive = true
} }
navigationController.setViewControllers(vcs, animated: true)
navigationController.setViewControllers(v, animated: true)
} else if let container = view.superview { } else if let container = view.superview {
let parentVC = presentingViewController let parentVC = presentingViewController
Motion.shared.transition(from: self, to: next, in: container) { finished in
if finished {
UIApplication.shared.keyWindow?.addSubview(next.view)
if let parentVC = parentVC { Motion.shared.transition(from: self, to: next, in: container) { [weak self] (isFinished) in
self.dismiss(animated: false) { guard isFinished else {
parentVC.present(next, animated: false, completion:nil) return
} }
} else {
UIApplication.shared.keyWindow?.addSubview(next.view)
guard let parentVC = parentVC else {
UIApplication.shared.keyWindow?.rootViewController = next UIApplication.shared.keyWindow?.rootViewController = next
return
} }
self?.dismiss(animated: false) {
parentVC.present(next, animated: false, completion: nil)
} }
} }
} }
......
...@@ -62,7 +62,7 @@ public class Motion: MotionController { ...@@ -62,7 +62,7 @@ public class Motion: MotionController {
/// progress of the current transition. 0 if no transition is happening /// progress of the current transition. 0 if no transition is happening
public override var progress: Double { public override var progress: Double {
didSet { didSet {
if transitioning { if isTransitioning {
transitionContext?.updateInteractiveTransition(CGFloat(progress)) transitionContext?.updateInteractiveTransition(CGFloat(progress))
} }
} }
...@@ -70,7 +70,7 @@ public class Motion: MotionController { ...@@ -70,7 +70,7 @@ public class Motion: MotionController {
public var isAnimating: Bool = false public var isAnimating: Bool = false
/// a UIViewControllerContextTransitioning object provided by UIKit, /// a UIViewControllerContextTransitioning object provided by UIKit,
/// might be nil when transitioning. This happens when calling motionReplaceViewController /// might be nil when isTransitioning. This happens when calling motionReplaceViewController
internal weak var transitionContext: UIViewControllerContextTransitioning? internal weak var transitionContext: UIViewControllerContextTransitioning?
internal var fullScreenSnapshot: UIView! internal var fullScreenSnapshot: UIView!
...@@ -129,7 +129,7 @@ public extension Motion { ...@@ -129,7 +129,7 @@ public extension Motion {
// internal methods for transition // internal methods for transition
internal extension Motion { internal extension Motion {
func start() { func start() {
guard transitioning else { return } guard isTransitioning else { return }
if let fvc = fromViewController, let tvc = toViewController { if let fvc = fromViewController, let tvc = toViewController {
closureProcessForMotionDelegate(vc: fvc) { closureProcessForMotionDelegate(vc: fvc) {
$0.motionWillStartTransition?() $0.motionWillStartTransition?()
...@@ -214,7 +214,7 @@ internal extension Motion { ...@@ -214,7 +214,7 @@ internal extension Motion {
} }
override func complete(finished: Bool) { override func complete(finished: Bool) {
guard transitioning else { return } guard isTransitioning else { return }
context.clean() context.clean()
if finished && presenting && toOverFullScreen { if finished && presenting && toOverFullScreen {
...@@ -304,7 +304,7 @@ internal extension Motion { ...@@ -304,7 +304,7 @@ internal extension Motion {
// custom transition helper, used in motion_replaceViewController // custom transition helper, used in motion_replaceViewController
internal extension Motion { internal extension Motion {
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 !transitioning else { return } guard !isTransitioning else { return }
presenting = true presenting = true
transitionContainer = view transitionContainer = view
fromViewController = from fromViewController = from
...@@ -341,7 +341,7 @@ internal extension Motion { ...@@ -341,7 +341,7 @@ internal extension Motion {
extension Motion: UIViewControllerAnimatedTransitioning { extension Motion: UIViewControllerAnimatedTransitioning {
public func animateTransition(using context: UIViewControllerContextTransitioning) { public func animateTransition(using context: UIViewControllerContextTransitioning) {
guard !transitioning else { return } guard !isTransitioning else { return }
transitionContext = context transitionContext = context
fromViewController = fromViewController ?? context.viewController(forKey: .from) fromViewController = fromViewController ?? context.viewController(forKey: .from)
toViewController = toViewController ?? context.viewController(forKey: .to) toViewController = toViewController ?? context.viewController(forKey: .to)
......
...@@ -40,7 +40,7 @@ public class MotionController: NSObject { ...@@ -40,7 +40,7 @@ public class MotionController: NSObject {
/// progress of the current transition. 0 if no transition is happening /// progress of the current transition. 0 if no transition is happening
public internal(set) var progress: Double = 0 { public internal(set) var progress: Double = 0 {
didSet { didSet {
if transitioning { if isTransitioning {
if let progressUpdateObservers = progressUpdateObservers { if let progressUpdateObservers = progressUpdateObservers {
for observer in progressUpdateObservers { for observer in progressUpdateObservers {
observer.motionDidUpdateProgress(progress: progress) observer.motionDidUpdateProgress(progress: progress)
...@@ -61,12 +61,12 @@ public class MotionController: NSObject { ...@@ -61,12 +61,12 @@ public class MotionController: NSObject {
} }
} }
/// whether or not we are doing a transition /// whether or not we are doing a transition
public var transitioning: Bool { public var isTransitioning: Bool {
return transitionContainer != nil return transitionContainer != nil
} }
/// container we created to hold all animating views, will be a subview of the /// container we created to hold all animating views, will be a subview of the
/// transitionContainer when transitioning /// transitionContainer when isTransitioning
public internal(set) var container: UIView! public internal(set) var container: UIView!
/// this is the container supplied by UIKit /// this is the container supplied by UIKit
...@@ -98,7 +98,7 @@ public class MotionController: NSObject { ...@@ -98,7 +98,7 @@ public class MotionController: NSObject {
} }
} }
func displayUpdate(_ link: CADisplayLink) { func displayUpdate(_ link: CADisplayLink) {
if transitioning, duration > 0, let beginTime = beginTime { if isTransitioning, duration > 0, let beginTime = beginTime {
let elapsedTime = CACurrentMediaTime() - beginTime let elapsedTime = CACurrentMediaTime() - beginTime
if elapsedTime > duration { if elapsedTime > duration {
...@@ -138,7 +138,7 @@ public extension MotionController { ...@@ -138,7 +138,7 @@ public extension MotionController {
- progress: the current progress, must be between -1...1 - progress: the current progress, must be between -1...1
*/ */
public func update(progress: Double) { public func update(progress: Double) {
guard transitioning else { return } guard isTransitioning else { return }
self.beginTime = nil self.beginTime = nil
self.progress = max(-1, min(1, progress)) self.progress = max(-1, min(1, progress))
} }
...@@ -149,7 +149,7 @@ public extension MotionController { ...@@ -149,7 +149,7 @@ public extension MotionController {
current state to the **end** state current state to the **end** state
*/ */
public func end(animate: Bool = true) { public func end(animate: Bool = true) {
guard transitioning else { return } guard isTransitioning else { return }
if !animate { if !animate {
self.complete(finished:true) self.complete(finished:true)
return return
...@@ -167,7 +167,7 @@ public extension MotionController { ...@@ -167,7 +167,7 @@ public extension MotionController {
current state to the **begining** state current state to the **begining** state
*/ */
public func cancel(animate: Bool = true) { public func cancel(animate: Bool = true) {
guard transitioning else { return } guard isTransitioning else { return }
if !animate { if !animate {
self.complete(finished:false) self.complete(finished:false)
return return
...@@ -196,7 +196,7 @@ public extension MotionController { ...@@ -196,7 +196,7 @@ public extension MotionController {
- view: the view to override to - view: the view to override to
*/ */
public func apply(modifiers: [MotionTransition], to view: UIView) { public func apply(modifiers: [MotionTransition], to view: UIView) {
guard transitioning else { return } guard isTransitioning else { return }
let targetState = MotionTargetState(modifiers: modifiers) let targetState = MotionTargetState(modifiers: modifiers)
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 {
...@@ -233,7 +233,7 @@ internal extension MotionController { ...@@ -233,7 +233,7 @@ internal extension MotionController {
/// must have transitionContainer set already /// must have transitionContainer set already
/// subclass should call context.set(fromViews:toViews) after inserting fromViews & toViews into the container /// subclass should call context.set(fromViews:toViews) after inserting fromViews & toViews into the container
func prepareForTransition() { func prepareForTransition() {
guard transitioning else { fatalError() } guard isTransitioning else { fatalError() }
plugins = Motion.enabledPlugins.map({ return $0.init() }) plugins = Motion.enabledPlugins.map({ return $0.init() })
processors = [ processors = [
IgnoreSubviewModifiersPreprocessor(), IgnoreSubviewModifiersPreprocessor(),
...@@ -273,14 +273,14 @@ internal extension MotionController { ...@@ -273,14 +273,14 @@ internal extension MotionController {
} }
func processContext() { func processContext() {
guard transitioning else { fatalError() } guard isTransitioning else { fatalError() }
for processor in processors { for processor in processors {
processor.process(fromViews: context.fromViews, toViews: context.toViews) processor.process(fromViews: context.fromViews, toViews: context.toViews)
} }
} }
func prepareForAnimation() { func prepareForAnimation() {
guard transitioning else { fatalError() } guard isTransitioning else { fatalError() }
animatingViews = [([UIView], [UIView])]() animatingViews = [([UIView], [UIView])]()
for animator in animators { for animator in animators {
let currentFromViews = context.fromViews.filter { (view: UIView) -> Bool in let currentFromViews = context.fromViews.filter { (view: UIView) -> Bool in
...@@ -296,7 +296,7 @@ internal extension MotionController { ...@@ -296,7 +296,7 @@ internal extension MotionController {
/// Actually animate the views /// Actually animate the views
/// subclass should call `prepareForTransition` & `prepareForAnimation` before calling `animate` /// subclass should call `prepareForTransition` & `prepareForAnimation` before calling `animate`
func animate() { func animate() {
guard transitioning else { fatalError() } guard isTransitioning else { fatalError() }
for (currentFromViews, currentToViews) in animatingViews { for (currentFromViews, currentToViews) in animatingViews {
// auto hide all animated views // auto hide all animated views
for view in currentFromViews { for view in currentFromViews {
...@@ -328,7 +328,7 @@ internal extension MotionController { ...@@ -328,7 +328,7 @@ internal extension MotionController {
} }
func complete(after: TimeInterval, finishing: Bool) { func complete(after: TimeInterval, finishing: Bool) {
guard transitioning else { fatalError() } guard isTransitioning else { fatalError() }
if after <= 0.001 { if after <= 0.001 {
complete(finished: finishing) complete(finished: finishing)
return return
...@@ -340,7 +340,7 @@ internal extension MotionController { ...@@ -340,7 +340,7 @@ internal extension MotionController {
} }
func complete(finished: Bool) { func complete(finished: Bool) {
guard transitioning else { fatalError() } guard isTransitioning else { fatalError() }
for animator in animators { for animator in animators {
animator.clean() animator.clean()
} }
......
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