Commit 9fa456da by Daniel Dahan

updated fromView and toView in MotionController to no longer use unwrapped optionals

parent 430cc140
...@@ -207,13 +207,13 @@ public class Motion: MotionController { ...@@ -207,13 +207,13 @@ public class Motion: MotionController {
} }
/// A reference to the fromView, fromViewController.view. /// A reference to the fromView, fromViewController.view.
internal var fromView: UIView { internal var fromView: UIView? {
return fromViewController!.view return fromViewController?.view
} }
/// A reference to the toView, toViewController.view. /// A reference to the toView, toViewController.view.
internal var toView: UIView { internal var toView: UIView? {
return toViewController!.view return toViewController?.view
} }
/// An initializer. /// An initializer.
...@@ -267,7 +267,11 @@ fileprivate extension Motion { ...@@ -267,7 +267,11 @@ fileprivate extension Motion {
internal extension Motion { internal extension Motion {
override func animate() { override func animate() {
context.unhide(view: toView) guard let tv = toView else {
return
}
context.unhide(view: tv)
updateContainerBackgroundColor() updateContainerBackgroundColor()
updateInsertOrder() updateInsertOrder()
...@@ -290,27 +294,34 @@ internal extension Motion { ...@@ -290,27 +294,34 @@ internal extension Motion {
return return
} }
guard let fv = fromView else {
return
}
guard let tv = toView else {
return
}
context.clean() context.clean()
if isFinished && isPresenting && toOverFullScreen { if isFinished && isPresenting && toOverFullScreen {
// finished presenting a overFullScreen VC // finished presenting a overFullScreen VC
context.unhide(rootView: toView) context.unhide(rootView: tv)
context.removeSnapshots(rootView: toView) context.removeSnapshots(rootView: tv)
context.storeViewAlpha(rootView: fromView) context.storeViewAlpha(rootView: fv)
fromViewController!.motionStoredSnapshot = container fromViewController!.motionStoredSnapshot = container
fromView.removeFromSuperview() fv.removeFromSuperview()
fromView.addSubview(c) fv.addSubview(c)
} else if !isFinished && !isPresenting && fromOverFullScreen { } else if !isFinished && !isPresenting && fromOverFullScreen {
// cancelled dismissing a overFullScreen VC // cancelled dismissing a overFullScreen VC
context.unhide(rootView: fromView) context.unhide(rootView: fv)
context.removeSnapshots(rootView: fromView) context.removeSnapshots(rootView: fv)
context.storeViewAlpha(rootView: toView) context.storeViewAlpha(rootView: tv)
toViewController!.motionStoredSnapshot = container toViewController!.motionStoredSnapshot = container
toView.removeFromSuperview() tv.removeFromSuperview()
toView.addSubview(c) tv.addSubview(c)
} else { } else {
context.unhideAll() context.unhideAll()
context.removeAllSnapshots() context.removeAllSnapshots()
...@@ -319,15 +330,15 @@ internal extension Motion { ...@@ -319,15 +330,15 @@ internal extension Motion {
// move fromView & toView back from our container back to the one supplied by UIKit // move fromView & toView back from our container back to the one supplied by UIKit
if (toOverFullScreen && isFinished) || (fromOverFullScreen && !isFinished) { if (toOverFullScreen && isFinished) || (fromOverFullScreen && !isFinished) {
tc.addSubview(isFinished ? fromView : toView) tc.addSubview(isFinished ? fv : tv)
} }
tc.addSubview(isFinished ? toView : fromView) tc.addSubview(isFinished ? tv : fv)
if isPresenting != isFinished, !isContainerController { if isPresenting != isFinished, !isContainerController {
// only happens when present a .overFullScreen VC // only happens when present a .overFullScreen VC
// bug: http://openradar.appspot.com/radar?id=5320103646199808 // bug: http://openradar.appspot.com/radar?id=5320103646199808
UIApplication.shared.keyWindow!.addSubview(isPresenting ? fromView : toView) UIApplication.shared.keyWindow!.addSubview(isPresenting ? fv : tv)
} }
// use temp variables to remember these values // use temp variables to remember these values
...@@ -378,7 +389,7 @@ fileprivate extension Motion { ...@@ -378,7 +389,7 @@ fileprivate extension Motion {
return return
} }
fullScreenSnapshot = v.window?.snapshotView(afterScreenUpdates: true) ?? fromView.snapshotView(afterScreenUpdates: true) fullScreenSnapshot = v.window?.snapshotView(afterScreenUpdates: true) ?? fromView?.snapshotView(afterScreenUpdates: true)
(v.window ?? transitionContainer)?.addSubview(fullScreenSnapshot) (v.window ?? transitionContainer)?.addSubview(fullScreenSnapshot)
if let v = fromViewController?.motionStoredSnapshot { if let v = fromViewController?.motionStoredSnapshot {
...@@ -398,23 +409,47 @@ fileprivate extension Motion { ...@@ -398,23 +409,47 @@ fileprivate extension Motion {
return return
} }
context.loadViewAlpha(rootView: toView) guard let fv = fromView else {
context.loadViewAlpha(rootView: fromView) return
v.addSubview(toView) }
v.addSubview(fromView)
guard let tv = toView else {
return
}
context.loadViewAlpha(rootView: tv)
context.loadViewAlpha(rootView: fv)
v.addSubview(tv)
v.addSubview(fv)
} }
/// Prepares the toView instance. /// Prepares the toView instance.
func prepareToView() { func prepareToView() {
toView.frame = fromView.frame guard let fv = fromView else {
toView.updateConstraints() return
toView.setNeedsLayout() }
toView.layoutIfNeeded()
guard let tv = toView else {
return
}
tv.frame = fv.frame
tv.updateConstraints()
tv.setNeedsLayout()
tv.layoutIfNeeded()
} }
/// Prepares the view hierarchy. /// Prepares the view hierarchy.
func prepareViewHierarchy() { func prepareViewHierarchy() {
context.set(fromViews: fromView.flattenedViewHierarchy, toViews: toView.flattenedViewHierarchy) guard let fv = fromView else {
return
}
guard let tv = toView else {
return
}
context.set(fromViews: fv.flattenedViewHierarchy, toViews: tv.flattenedViewHierarchy)
} }
} }
...@@ -426,7 +461,12 @@ internal extension Motion { ...@@ -426,7 +461,12 @@ internal extension Motion {
override func prepareTransitionPairs() { override func prepareTransitionPairs() {
super.prepareTransitionPairs() super.prepareTransitionPairs()
context.hide(view: toView)
guard let tv = toView else {
return
}
context.hide(view: tv)
} }
} }
...@@ -560,7 +600,7 @@ fileprivate extension Motion { ...@@ -560,7 +600,7 @@ fileprivate extension Motion {
if let v = containerBackgroundColor { if let v = containerBackgroundColor {
container?.backgroundColor = v container?.backgroundColor = v
} else if !toOverFullScreen && !fromOverFullScreen { } else if !toOverFullScreen && !fromOverFullScreen {
container?.backgroundColor = toView.backgroundColor container?.backgroundColor = toView?.backgroundColor
} }
} }
......
...@@ -197,6 +197,14 @@ class TransitionPreprocessor: MotionPreprocessor { ...@@ -197,6 +197,14 @@ class TransitionPreprocessor: MotionPreprocessor {
return return
} }
guard let fv = m.fromView else {
return
}
guard let tv = m.toView else {
return
}
var defaultAnimation = m.defaultAnimation var defaultAnimation = m.defaultAnimation
let isNavigationController = m.isNavigationController let isNavigationController = m.isNavigationController
let isTabBarController = m.isTabBarController let isTabBarController = m.isTabBarController
...@@ -205,10 +213,8 @@ class TransitionPreprocessor: MotionPreprocessor { ...@@ -205,10 +213,8 @@ class TransitionPreprocessor: MotionPreprocessor {
let isPresenting = m.isPresenting let isPresenting = m.isPresenting
let fromOverFullScreen = m.fromOverFullScreen let fromOverFullScreen = m.fromOverFullScreen
let toOverFullScreen = m.toOverFullScreen let toOverFullScreen = m.toOverFullScreen
let toView = m.toView
let fromView = m.fromView
let animators = m.animators let animators = m.animators
if case .auto = defaultAnimation { if case .auto = defaultAnimation {
if isNavigationController, let navAnim = toViewController?.navigationController?.motionNavigationTransitionType { if isNavigationController, let navAnim = toViewController?.navigationController?.motionNavigationTransitionType {
defaultAnimation = navAnim defaultAnimation = navAnim
...@@ -226,7 +232,7 @@ class TransitionPreprocessor: MotionPreprocessor { ...@@ -226,7 +232,7 @@ class TransitionPreprocessor: MotionPreprocessor {
} }
if case .auto = defaultAnimation { if case .auto = defaultAnimation {
if animators!.contains(where: { $0.canAnimate(view: toView, isAppearing: true) || $0.canAnimate(view: fromView, isAppearing: false) }) { if animators!.contains(where: { $0.canAnimate(view: tv, isAppearing: true) || $0.canAnimate(view: fv, isAppearing: false) }) {
defaultAnimation = .none defaultAnimation = .none
} else if isNavigationController { } else if isNavigationController {
...@@ -244,8 +250,8 @@ class TransitionPreprocessor: MotionPreprocessor { ...@@ -244,8 +250,8 @@ class TransitionPreprocessor: MotionPreprocessor {
return return
} }
context[fromView] = [.timingFunction(.standard), .duration(0.35)] context[fv] = [.timingFunction(.standard), .duration(0.35)]
context[toView] = [.timingFunction(.standard), .duration(0.35)] context[tv] = [.timingFunction(.standard), .duration(0.35)]
let shadowState: [MotionTransition] = [.shadow(opacity: 0.5), let shadowState: [MotionTransition] = [.shadow(opacity: 0.5),
.shadow(color: .black), .shadow(color: .black),
...@@ -255,93 +261,93 @@ class TransitionPreprocessor: MotionPreprocessor { ...@@ -255,93 +261,93 @@ class TransitionPreprocessor: MotionPreprocessor {
switch defaultAnimation { switch defaultAnimation {
case .push(let direction): case .push(let direction):
context[toView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true)), context[tv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true)),
.shadow(opacity: 0), .shadow(opacity: 0),
.beginWith(transitions: shadowState), .beginWith(transitions: shadowState),
.timingFunction(.deceleration)]) .timingFunction(.deceleration)])
context[fromView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false) / 3), context[fv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false) / 3),
.overlay(color: .black, opacity: 0.1), .overlay(color: .black, opacity: 0.1),
.timingFunction(.deceleration)]) .timingFunction(.deceleration)])
case .pull(let direction): case .pull(let direction):
m.insertToViewFirst = true m.insertToViewFirst = true
context[fromView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false)), context[fv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false)),
.shadow(opacity: 0), .shadow(opacity: 0),
.beginWith(transitions: shadowState)]) .beginWith(transitions: shadowState)])
context[toView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true) / 3), context[tv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true) / 3),
.overlay(color: .black, opacity: 0.1)]) .overlay(color: .black, opacity: 0.1)])
case .slide(let direction): case .slide(let direction):
context[fromView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false))]) context[fv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false))])
context[toView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true))]) context[tv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true))])
case .zoomSlide(let direction): case .zoomSlide(let direction):
context[fromView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false)), .scale(to: 0.8)]) context[fv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false)), .scale(to: 0.8)])
context[toView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true)), .scale(to: 0.8)]) context[tv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true)), .scale(to: 0.8)])
case .cover(let direction): case .cover(let direction):
context[toView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true)), context[tv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true)),
.shadow(opacity: 0), .shadow(opacity: 0),
.beginWith(transitions: shadowState), .beginWith(transitions: shadowState),
.timingFunction(.deceleration)]) .timingFunction(.deceleration)])
context[fromView]!.append(contentsOf: [.overlay(color: .black, opacity: 0.1), context[fv]!.append(contentsOf: [.overlay(color: .black, opacity: 0.1),
.timingFunction(.deceleration)]) .timingFunction(.deceleration)])
case .uncover(let direction): case .uncover(let direction):
m.insertToViewFirst = true m.insertToViewFirst = true
context[fromView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false)), context[fv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false)),
.shadow(opacity: 0), .shadow(opacity: 0),
.beginWith(transitions: shadowState)]) .beginWith(transitions: shadowState)])
context[toView]!.append(contentsOf: [.overlay(color: .black, opacity: 0.1)]) context[tv]!.append(contentsOf: [.overlay(color: .black, opacity: 0.1)])
case .pageIn(let direction): case .pageIn(let direction):
context[toView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true)), context[tv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: true)),
.shadow(opacity: 0), .shadow(opacity: 0),
.beginWith(transitions: shadowState), .beginWith(transitions: shadowState),
.timingFunction(.deceleration)]) .timingFunction(.deceleration)])
context[fromView]!.append(contentsOf: [.scale(to: 0.7), context[fv]!.append(contentsOf: [.scale(to: 0.7),
.overlay(color: .black, opacity: 0.1), .overlay(color: .black, opacity: 0.1),
.timingFunction(.deceleration)]) .timingFunction(.deceleration)])
case .pageOut(let direction): case .pageOut(let direction):
m.insertToViewFirst = true m.insertToViewFirst = true
context[fromView]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false)), context[fv]!.append(contentsOf: [.translate(to: shift(direction: direction, isAppearing: false)),
.shadow(opacity: 0), .shadow(opacity: 0),
.beginWith(transitions: shadowState)]) .beginWith(transitions: shadowState)])
context[toView]!.append(contentsOf: [.scale(to: 0.7), context[tv]!.append(contentsOf: [.scale(to: 0.7),
.overlay(color: .black, opacity: 0.1)]) .overlay(color: .black, opacity: 0.1)])
case .fade: case .fade:
// TODO: clean up this. overFullScreen logic shouldn't be here // TODO: clean up this. overFullScreen logic shouldn't be here
if !(fromOverFullScreen && !isPresenting) { if !(fromOverFullScreen && !isPresenting) {
context[toView] = [.fade] context[tv] = [.fade]
} }
#if os(tvOS) #if os(tvOS)
context[fromView] = [.fade] context[fromView] = [.fade]
#else #else
if (!isPresenting && toOverFullScreen) || !fromView.isOpaque || (fromView.backgroundColor?.alphaComponent ?? 1) < 1 { if (!isPresenting && toOverFullScreen) || !fv.isOpaque || (fv.backgroundColor?.alphaComponent ?? 1) < 1 {
context[fromView] = [.fade] context[fv] = [.fade]
} }
#endif #endif
context[toView]!.append(.preferredDurationMatchesLongest) context[tv]!.append(.preferredDurationMatchesLongest)
context[fromView]!.append(.preferredDurationMatchesLongest) context[fv]!.append(.preferredDurationMatchesLongest)
case .zoom: case .zoom:
m.insertToViewFirst = true m.insertToViewFirst = true
context[fromView]!.append(contentsOf: [.scale(to: 1.3), .fade]) context[fv]!.append(contentsOf: [.scale(to: 1.3), .fade])
context[toView]!.append(contentsOf: [.scale(to: 0.7)]) context[tv]!.append(contentsOf: [.scale(to: 0.7)])
case .zoomOut: case .zoomOut:
context[toView]!.append(contentsOf: [.scale(to: 1.3), .fade]) context[tv]!.append(contentsOf: [.scale(to: 1.3), .fade])
context[fromView]!.append(contentsOf: [.scale(to: 0.7)]) context[fv]!.append(contentsOf: [.scale(to: 0.7)])
default: default:
fatalError("Not implemented") fatalError("Not implemented")
......
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