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,249 +28,329 @@ ...@@ -28,249 +28,329 @@
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
var storedSnapshot: UIView? fileprivate struct AssociatedInstance {
var previousNavigationDelegate: UINavigationControllerDelegate? /// A reference to the modal animation.
var previousTabBarDelegate: UITabBarControllerDelegate? 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?
/**
A reference to the previous navigation controller delegate
before Motion was enabled.
*/
var previousNavigationDelegate: UINavigationControllerDelegate?
/**
A reference to the previous tab bar controller delegate
before Motion was enabled.
*/
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)
}
}
/// default motion animation type for presenting & dismissing modally
public var motionModalAnimationType: MotionDefaultAnimationType {
get {
return associatedInstance.modalAnimationType
}
set(value) {
associatedInstance.modalAnimationType = value
}
}
@IBInspectable
public var motionModalAnimationTypeString: String? {
get {
return associatedInstance.modalAnimationType.label
}
set(value) {
associatedInstance.modalAnimationType = value?.parseOne() ?? .auto
}
}
internal var motionConfig: MotionViewControllerConfig { /// used for .overFullScreen presentation
get { internal var motionStoredSnapshot: UIView? {
if let config = objc_getAssociatedObject(self, &AssociatedKeys.motionConfig) as? MotionViewControllerConfig { get {
return config return associatedInstance.storedSnapshot
} }
let config = MotionViewControllerConfig() set(value) {
self.motionConfig = config associatedInstance.storedSnapshot = value
return config }
}
/**
A reference to the previous navigation controller delegate
before Motion was enabled.
*/
internal var previousNavigationDelegate: UINavigationControllerDelegate? {
get {
return associatedInstance.previousNavigationDelegate
}
set(value) {
associatedInstance.previousNavigationDelegate = value
}
} }
set { objc_setAssociatedObject(self, &AssociatedKeys.motionConfig, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
}
internal var previousNavigationDelegate: UINavigationControllerDelegate? { /**
get { return motionConfig.previousNavigationDelegate } A reference to the previous tab bar controller delegate
set { motionConfig.previousNavigationDelegate = newValue } before Motion was enabled.
} */
internal var previousTabBarDelegate: UITabBarControllerDelegate? {
get {
return associatedInstance.previousTabBarDelegate
}
set(value) {
associatedInstance.previousTabBarDelegate = value
}
}
///A boolean that indicates whether Motion is enabled or disabled.
@IBInspectable
public var isMotionEnabled: Bool {
get {
return transitioningDelegate is Motion
}
set(value) {
guard value != isMotionEnabled else {
return
}
internal var previousTabBarDelegate: UITabBarControllerDelegate? { if value {
get { return motionConfig.previousTabBarDelegate } transitioningDelegate = Motion.shared
set { motionConfig.previousTabBarDelegate = newValue }
}
/// used for .overFullScreen presentation if let v = self as? UINavigationController {
internal var motionStoredSnapshot: UIView? { previousNavigationDelegate = v.delegate
get { return motionConfig.storedSnapshot } v.delegate = Motion.shared
set { motionConfig.storedSnapshot = newValue } }
}
/// default motion animation type for presenting & dismissing modally if let v = self as? UITabBarController {
public var motionModalAnimationType: MotionDefaultAnimationType { previousTabBarDelegate = v.delegate
get { return motionConfig.modalAnimation } v.delegate = Motion.shared
set { motionConfig.modalAnimation = newValue } }
} } else {
transitioningDelegate = nil
@IBInspectable public var motionModalAnimationTypeString: String? { if let v = self as? UINavigationController, v.delegate is Motion {
get { return motionConfig.modalAnimation.label } v.delegate = previousNavigationDelegate
set { motionConfig.modalAnimation = newValue?.parseOne() ?? .auto } }
}
@IBInspectable public var isMotionEnabled: Bool { if let v = self as? UITabBarController, v.delegate is Motion {
get { v.delegate = previousTabBarDelegate
return transitioningDelegate is Motion }
}
}
} }
}
set { extension UINavigationController {
guard newValue != isMotionEnabled else { return } /// Default motion animation type for push and pop within the navigation controller.
if newValue { public var motionNavigationAnimationType: MotionDefaultAnimationType {
transitioningDelegate = Motion.shared get {
if let navi = self as? UINavigationController { return associatedInstance.navigationAnimationType
previousNavigationDelegate = navi.delegate
navi.delegate = Motion.shared
} }
if let tab = self as? UITabBarController { set(value) {
previousTabBarDelegate = tab.delegate associatedInstance.navigationAnimationType = value
tab.delegate = Motion.shared
} }
} else { }
transitioningDelegate = nil
if let navi = self as? UINavigationController, navi.delegate is Motion { /// A String representation for the motionNavigationAnimationType.
navi.delegate = previousNavigationDelegate @IBInspectable
public var motionNavigationAnimationTypeString: String? {
get {
return associatedInstance.navigationAnimationType.label
} }
if let tab = self as? UITabBarController, tab.delegate is Motion { set(value) {
tab.delegate = previousTabBarDelegate associatedInstance.navigationAnimationType = value?.parseOne() ?? .auto
} }
}
} }
}
}
extension UINavigationController {
/// default motion animation type for push and pop within the navigation controller
public var motionNavigationAnimationType: MotionDefaultAnimationType {
get { return motionConfig.navigationAnimation }
set { motionConfig.navigationAnimation = newValue }
}
@IBInspectable public var motionNavigationAnimationTypeString: String? {
get { return motionConfig.navigationAnimation.label }
set { motionConfig.navigationAnimation = newValue?.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 } }
}
/// A String representation for the motionTabBarAnimationTypeString.
@IBInspectable
public var motionTabBarAnimationTypeString: String? {
get {
return associatedInstance.tabBarAnimationType.label }
set(value) {
associatedInstance.tabBarAnimationType = value?.parseOne() ?? .auto
}
}
} }
extension UIViewController { extension UIViewController {
@available(*, deprecated: 0.1.4, message: "use motion_dismissViewController instead") /**
@IBAction public func ht_dismiss(_ sender: UIView) { Dismiss the current view controller with animation. Will perform a
motion_dismissViewController() navigationController.popViewController if the current view controller
} is contained inside a navigationController
*/
@available(*, deprecated: 0.1.4, message: "use motion_replaceViewController(with:) instead") @IBAction
public func motionReplaceViewController(with next: UIViewController) { public func motion_dismissViewController() {
motion_replaceViewController(with: next) if let navigationController = navigationController, navigationController.viewControllers.first != self {
} navigationController.popViewController(animated: true)
} else {
/** dismiss(animated: true, completion: nil)
Dismiss the current view controller with animation. Will perform a navigationController.popViewController }
if the current view controller is contained inside a navigationController
*/
@IBAction public func motion_dismissViewController() {
if let navigationController = navigationController, navigationController.viewControllers.first != self {
navigationController.popViewController(animated: true)
} else {
dismiss(animated: true, completion: nil)
} }
}
/// Unwind to the root view controller using Motion.
/** @IBAction
Unwind to the root view controller using Motion public func motion_unwindToRootViewController() {
*/ motion_unwindToViewController { $0.presentingViewController == nil }
@IBAction public func motion_unwindToRootViewController() { }
motion_unwindToViewController { $0.presentingViewController == nil }
} /// Unwind to a specific view controller using Motion.
public func motion_unwindToViewController(_ toViewController: UIViewController) {
/** motion_unwindToViewController { $0 == toViewController }
Unwind to a specific view controller using Motion }
*/
public func motion_unwindToViewController(_ toViewController: UIViewController) { /// Unwind to a view controller that responds to the given selector using Motion.
motion_unwindToViewController { $0 == toViewController } public func motion_unwindToViewController(withSelector: Selector) {
} motion_unwindToViewController { $0.responds(to: withSelector) }
}
/**
Unwind to a view controller that responds to the given selector using Motion /// Unwind to a view controller with given class using Motion
*/ public func motion_unwindToViewController(withClass: AnyClass) {
public func motion_unwindToViewController(withSelector: Selector) { motion_unwindToViewController { $0.isKind(of: withClass) }
motion_unwindToViewController { $0.responds(to: withSelector) } }
}
/// Unwind to a view controller that the matchBlock returns true on.
/** public func motion_unwindToViewController(withMatchBlock: (UIViewController) -> Bool) {
Unwind to a view controller with given class using Motion var target: UIViewController?
*/ var current: UIViewController? = self
public func motion_unwindToViewController(withClass: AnyClass) {
motion_unwindToViewController { $0.isKind(of: withClass) } while nil == target && nil != current {
} if let childViewControllers = (current as? UINavigationController)?.childViewControllers ?? current!.navigationController?.childViewControllers {
for v in childViewControllers.reversed() {
/** if self != v, withMatchBlock(v) {
Unwind to a view controller that the matchBlock returns true on. target = v
*/ break
public func motion_unwindToViewController(withMatchBlock: (UIViewController) -> Bool) { }
var target: UIViewController? = nil }
var current: UIViewController? = self }
while target == nil && current != nil { guard nil == target else {
if let childViewControllers = (current as? UINavigationController)?.childViewControllers ?? current!.navigationController?.childViewControllers { continue
for vc in childViewControllers.reversed() { }
if vc != self, withMatchBlock(vc) {
target = vc current = current?.presentingViewController
break
} guard let v = current, withMatchBlock(v) else {
continue
}
target = v
} }
}
if target == nil { guard let v = target else {
current = current!.presentingViewController return
if let vc = current, withMatchBlock(vc) == true {
target = vc
} }
}
} guard nil != v.presentedViewController else {
v.navigationController?.popToViewController(v, animated: true)
if let target = target { return
if target.presentedViewController != nil { }
_ = target.navigationController?.popToViewController(target, animated: false)
v.navigationController?.popToViewController(v, 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
Motion.shared.fromViewController = fromVC And also force Motion to use the current view controller as the fromViewController.
let snapshotView = fromVC.view.snapshotView(afterScreenUpdates: true)! */
toVC.presentedViewController!.view.addSubview(snapshotView) Motion.shared.fromViewController = fromVC
guard let snapshot = fromVC.view.snapshotView(afterScreenUpdates: true) else {
return
}
toVC.presentedViewController?.view.addSubview(snapshot)
} }
toVC.dismiss(animated: true, completion: nil) toVC.dismiss(animated: true, completion: nil)
} else {
_ = target.navigationController?.popToViewController(target, animated: true)
}
} else {
// unwind target not found
}
}
/**
Replace the current view controller with another VC on the navigation/modal stack.
*/
public func motion_replaceViewController(with next: UIViewController) {
if Motion.shared.transitioning {
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
} }
if let navigationController = navigationController {
var vcs = navigationController.childViewControllers /**
if !vcs.isEmpty { Replace the current view controller with another view controller on the
vcs.removeLast() navigation/modal stack.
vcs.append(next) */
} public func motion_replaceViewController(with next: UIViewController) {
if navigationController.isMotionEnabled { guard !Motion.shared.isTransitioning else {
Motion.shared.forceNotInteractive = true 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
navigationController.setViewControllers(vcs, animated: true) }
} else if let container = view.superview {
let parentVC = presentingViewController if let navigationController = navigationController {
Motion.shared.transition(from: self, to: next, in: container) { finished in var v = navigationController.childViewControllers
if finished {
UIApplication.shared.keyWindow?.addSubview(next.view) if !v.isEmpty {
v.removeLast()
if let parentVC = parentVC { v.append(next)
self.dismiss(animated: false) { }
parentVC.present(next, animated: false, completion:nil)
if navigationController.isMotionEnabled {
Motion.shared.forceNotInteractive = true
}
navigationController.setViewControllers(v, animated: true)
} else if let container = view.superview {
let parentVC = presentingViewController
Motion.shared.transition(from: self, to: next, in: container) { [weak self] (isFinished) in
guard isFinished else {
return
}
UIApplication.shared.keyWindow?.addSubview(next.view)
guard let parentVC = parentVC else {
UIApplication.shared.keyWindow?.rootViewController = next
return
}
self?.dismiss(animated: false) {
parentVC.present(next, animated: false, completion: nil)
}
} }
} else {
UIApplication.shared.keyWindow?.rootViewController = next
}
} }
}
} }
}
} }
...@@ -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