IOS 10 Interractive transition - ios

Swift 3 - IOS 10 - Xcode 8
I want create an interactive transition. I have two view controller :
RootViewController (Source - SVC)
PlayerViewController (Destination - DVC)
But, when my DVC is presented, it never execute my animation and related methods. It execute the system animation.
My RootViewController :
class RootViewController: UIViewController {
var transitionManager = PlayerTransitionManager()
override func viewDidLoad() {
super.viewDidLoad()
self.transitionManager.sourceViewController = self
// ...
}
}
My TransitionManager :
class PlayerTransitionManager: UIPercentDrivenInteractiveTransition, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
private var presenting = false
private var interactive = false
private var enterPanGesture: UIPanGestureRecognizer!
private var exitPanGesture: UIPanGestureRecognizer!
var sourceViewController: RootViewController! {
didSet {
self.enterPanGesture = UIPanGestureRecognizer()
self.enterPanGesture.addTarget(self, action:#selector(PlayerTransitionManager.handleOnstagePan(_:)))
self.sourceViewController.playerV.addGestureRecognizer(self.enterPanGesture)
}
}
var destinationViewController: UIViewController! {
didSet {
self.exitPanGesture = UIPanGestureRecognizer()
self.exitPanGesture.addTarget(self, action:#selector(PlayerTransitionManager.handleOffstagePan(_:)))
self.destinationViewController.view.addGestureRecognizer(self.exitPanGesture)
}
}
func handleOnstagePan(_ pan: UIPanGestureRecognizer){
let translation = pan.translation(in: pan.view!)
let d = translation.y / pan.view!.bounds.height * -0.5
switch (pan.state) {
case .began:
self.interactive = true
let storyboard = UIStoryboard(name: "Main", bundle: nil) // OK
let controller = storyboard.instantiateViewController(withIdentifier: "PlayerVC") // OK
controller.transitioningDelegate = self
controller.modalPresentationStyle = .custom
self.destinationViewController = controller
self.sourceViewController.present(controller, animated: true, completion: nil) // present with system annimation
break
case .changed:
// Never Executed
self.update(d)
break
default: // .Ended, .Cancelled, .Failed ...
// Finish or cancel.
// No impact because annimation never started
break
}
}
func handleOffstagePan(_ pan: UIPanGestureRecognizer){
// For dismiss
// Same problem
}
// MARK: UIViewControllerAnimatedTransitioning protocol methods
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// Nerver Executed
// ...
}
func offStage(amount: CGFloat) -> CGAffineTransform {
// Nerver Executed
// ...
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
// Nerver Executed
// ...
}
// MARK: UIViewControllerTransitioningDelegate protocol methods
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
// Nerver Executed
// ...
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
// Nerver Executed
// ...
}
func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
// Nerver Executed
// ...
}
func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
// Nerver Executed
// ...
}
}

Related

CABasicAnimation with UINavigatonController and custom animations goes wrong

Here below you can see the result of my code. Please note that the second time when I press in the Back Button the animation is not working.
Best Regards
I have tried for hours to understand what is the trouble with my animation, but I can't find the source of the problem. I have been looking around the internet for an answer without success. So, this is my problem.
I put the animation to finish() if the transition goes more than 50% of the view.bounds.width and cancel() otherwise
This is my steps
Handle the Animation to less than 50%
The animations goes back
Press the Back button in the UINavigationItem and the animation runs to fast
This my code in the Animator
class Animator: UIPercentDrivenInteractiveTransition, UIViewControllerAnimatedTransitioning {
private var pausedTime: CFTimeInterval = 0
private var isLayerBased: Bool { operation == .pop }
let animationDuration = 1.0
weak var storedContext: UIViewControllerContextTransitioning?
var interactive: Bool = false
var operation: UINavigationController.Operation = .push
func handlePan(recognizer: UIScreenEdgePanGestureRecognizer)
{
// This part is only for get percent of the translation in the screen with the finger
let translation = recognizer.translation(in: recognizer.view!.superview!)
var progress: CGFloat = abs(translation.x / recognizer.view!.superview!.bounds.width)
progress = min(max(progress, 0.01), 0.99)
switch recognizer.state {
case .changed:
update(progress)
case .cancelled, .ended:
if progress < 0.5 {
cancel()
} else {
finish()
}
interactive = false
default:
break
}
}
override func update(_ percentComplete: CGFloat) {
super.update(percentComplete)
if isLayerBased {
let animationProgress = TimeInterval(animationDuration) * TimeInterval(percentComplete)
storedContext?.containerView.layer.timeOffset = pausedTime + animationProgress
}
}
override func cancel() {
if isLayerBased {
restart(forFinishing: false)
}
super.cancel()
}
override func finish() {
if isLayerBased {
restart(forFinishing: true)
}
super.finish()
}
private func restart(forFinishing: Bool)
{
let transitionLayer = storedContext?.containerView.layer
transitionLayer?.beginTime = CACurrentMediaTime()
transitionLayer?.speed = forFinishing ? 1 : -1
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
{
if interactive && isLayerBased {
let transitionLayer = transitionContext.containerView.layer
self.pausedTime = transitionLayer.convertTime(CACurrentMediaTime(), from: nil)
transitionLayer.speed = 0
transitionLayer.timeOffset = pausedTime
}
self.storedContext = transitionContext
if operation == .pop {
let fromVC = transitionContext.viewController(forKey: .from)!
let toVC = transitionContext.viewController(forKey: .to)!
let animation = CABasicAnimation(keyPath: "transform")
animation.fromValue = NSValue(caTransform3D: CATransform3DIdentity)
animation.toValue = NSValue(caTransform3D: CATransform3DMakeScale(0.001, 0.001, 1))
animation.duration = animationDuration
animation.delegate = self
fromVC.view.layer.removeAllAnimations()
fromVC.view.layer.add(animation, forKey: nil)
} else if operation == .push {
// The Push Animation
// ...
}
}
}
extension Animator: CAAnimationDelegate {
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if let context = self.storedContext
{
print("COMPLETE TRANSITION & ANIMATION STOP")
context.completeTransition(!context.transitionWasCancelled)
}
self.storedContext = nil
}
}
That was my animator class. In my MainViewController the only interesting code is this:
class MainViewController: UIViewController, UINavigationControllerDelegate {
let animator = Animator()
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.delegate = self
}
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animator.operation = operation
return animador
}
func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
if ! animator.interactive {
return nil
}
return animador
}
}
And in my DetailViewController I have this
class DetailViewController: UIViewController {
weak var animator: Animator?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let masterVC = navigationController!.viewControllers.first as? ViewController {
animador = masterVC.animador
}
let pan = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(didPan(recognizer:)))
pan.edges = .left
view.addGestureRecognizer(pan)
}
#objc func didPan(recognizer: UIScreenEdgePanGestureRecognizer)
{
if recognizer.state == .began
{
animador?.interactive = true
self.navigationController?.popViewController(animated: true)
}
animador?.handlePan(recognizer: recognizer)
}

viewController Present when I dismissed it

I have a viewcontroller which is segue to a tableViewController and I want to present it with transition and as a sideMenu from top I find some code and it's working fine but i cant understand the part when i dismiss the ViewController it present itself
//
// ViewController.swift
// ProTansition
//
// Created by Teodik Abrami on 11/1/18.
// Copyright © 2018 Teodik Abrami. All rights reserved.
//
import UIKit
class ViewController: UIViewController, MenuTransitionManagerDelegate {
func dismiss() {
dismiss(animated: true, completion: nil)
print("dismiss run")
}
var menuTransition = MenuTransitionManager()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
print("ViewController Appear")
}
override func viewDidDisappear(_ animated: Bool) {
print("viewcontroller disapear")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinaion = segue.destination
destinaion.transitioningDelegate = menuTransition
menuTransition.delegate = self
}
}
tableView is a normal tableview with 5 rows and no special code in it
and the transition
//
// MenuTransitionManager.swift
// ProTansition
//
// Created by Teodik Abrami on 11/1/18.
// Copyright © 2018 Teodik Abrami. All rights reserved.
//
import Foundation
import UIKit
#objc protocol MenuTransitionManagerDelegate {
func dismiss()
}
class MenuTransitionManager: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
let duration = 2.0
var isPresenting = false
var delegate: MenuTransitionManagerDelegate?
var snapShot: UIView? {
didSet {
if let delegate = delegate {
let tap = UITapGestureRecognizer(target: delegate, action: #selector(delegate.dismiss))
snapShot?.addGestureRecognizer(tap)
}
}
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from) else {
return
}
guard let toView = transitionContext.view(forKey: UITransitionContextViewKey.to) else {
return
}
let container = transitionContext.containerView
let moveDown = CGAffineTransform.init(translationX: 0, y: container.frame.height - 150)
if isPresenting {
container.addSubview(toView)
snapShot = fromView.snapshotView(afterScreenUpdates: true)
container.addSubview(snapShot!)
}
UIView.animateKeyframes(withDuration: duration, delay: 0, options: [], animations: {
if self.isPresenting {
self.snapShot?.transform = moveDown
} else {
self.snapShot?.transform = CGAffineTransform.identity
}
}) { (finished) in
transitionContext.completeTransition(true)
if !self.isPresenting {
self.snapShot?.removeFromSuperview()
}
}
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
isPresenting = true
return self
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
isPresenting = false
return self
}
}
I add tapgesture to snapshot and when its tapped protocol works and dismiss in viewcontroller works and the viewController appears I dont understand why and even why codes run on a controller that are not presented
this is the view controller that i cant figured out why it present when i dismiss it
this happend when menuButton pressed
Your whole strategy of setting isPresenting = true or isPresenting = false is doomed to failure, as both pieces of code will run on both occasions. You have to distinguish presentation from dismissal by using two different animationController objects (instead of returning self both times) or by looking to see which view controller is the from view controller and which is the to view controller.

UIPresentationController change size for a moment when another view is on top

I am trying to make a pop over form the bottom of screen using UIPresentationController, so I followed raywenderlich guide here : https://www.raywenderlich.com/139277/uipresentationcontroller-tutorial-getting-started. I did the exact same thing, I only change the size and y position of the frame. The pop up consist of buttons that open the share sheet , but for some reason when I open the sheet then click "save to files", the "shave to files" view shows up and when I hit cancel my pop over goes full screen for a moment then changes to my custom size.
I tried to debug the app and found out that containerViewWillLayoutSubviews() doesn't get called untill the "save to file" view is dismissed. Anyone have an idea on how to solve this. Thank you
this is my code :
main :
final class MainViewController: UIViewController {
// MARK: - Properties
lazy var slideInTransitioningDelegate = SlideInPresentationManager()
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func showPopup(_ sender: Any) {
let controller = storyboard.instantiateViewController(withIdentifier: NSStringFromClass(MyPopUpController.self))
as! MyPopUpController
slideInTransitioningDelegate.direction = .bottom
slideInTransitioningDelegate.disableCompactHeight = true
controller.transitioningDelegate = slideInTransitioningDelegate
controller.modalPresentationStyle = .custom
}
mypopucontroller
final class MyPopUpController: UIViewController {
#IBAction func share(_ sender: Any) {
let activityController = UIActivityViewController(activityItems: ["message"], applicationActivities: nil)
present(activityController, animated: true)
}
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
}
slide in presentation controller :
final class SlideInPresentationController: UIPresentationController {
// MARK: - Properties
fileprivate var dimmingView: UIView!
private var direction: PresentationDirection
override var frameOfPresentedViewInContainerView: CGRect {
var frame: CGRect = .zero
frame.size = size(forChildContentContainer: presentedViewController, withParentContainerSize: containerView!.bounds.size)
switch direction {
case .right:
frame.origin.x = containerView!.frame.width*(1.0/3.0)
case .bottom:
frame.origin.y = containerView!.frame.height*0.5
default:
frame.origin = .zero
}
return frame
}
// MARK: - Initializers
init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?, direction: PresentationDirection) {
self.direction = direction
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
setupDimmingView()
}
override func presentationTransitionWillBegin() {
containerView?.insertSubview(dimmingView, at: 0)
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|[dimmingView]|", options: [], metrics: nil, views: ["dimmingView": dimmingView]))
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "H:|[dimmingView]|", options: [], metrics: nil, views: ["dimmingView": dimmingView]))
guard let coordinator = presentedViewController.transitionCoordinator else {
dimmingView.alpha = 1.0
return
}
coordinator.animate(alongsideTransition: { _ in
self.dimmingView.alpha = 1.0
})
}
override func dismissalTransitionWillBegin() {
guard let coordinator = presentedViewController.transitionCoordinator else {
dimmingView.alpha = 0.0
return
}
coordinator.animate(alongsideTransition: { _ in
self.dimmingView.alpha = 0.0
})
}
override func containerViewWillLayoutSubviews() {
presentedView?.frame = frameOfPresentedViewInContainerView
}
override func size(forChildContentContainer container: UIContentContainer, withParentContainerSize parentSize: CGSize) -> CGSize {
switch direction {
case .left, .right:
return CGSize(width: parentSize.width*(2.0/3.0), height: parentSize.height)
case .bottom, .top:
return CGSize(width: parentSize.width, height: parentSize.height*0.67)
}
}
}
// MARK: - Private
private extension SlideInPresentationController {
func setupDimmingView() {
dimmingView = UIView()
dimmingView.translatesAutoresizingMaskIntoConstraints = false
dimmingView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
dimmingView.alpha = 0.0
let recognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap(recognizer:)))
dimmingView.addGestureRecognizer(recognizer)
}
dynamic func handleTap(recognizer: UITapGestureRecognizer) {
presentingViewController.dismiss(animated: true)
}
}
slidein manager :
final class SlideInPresentationManager: NSObject {
// MARK: - Properties
var direction = PresentationDirection.left
var disableCompactHeight = false
}
// MARK: - UIViewControllerTransitioningDelegate
extension SlideInPresentationManager: UIViewControllerTransitioningDelegate {
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
let presentationController = SlideInPresentationController(presentedViewController: presented, presenting: presenting, direction: direction)
presentationController.delegate = self
return presentationController
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return SlideInPresentationAnimator(direction: direction, isPresentation: true)
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return SlideInPresentationAnimator(direction: direction, isPresentation: false)
}
}
// MARK: - UIAdaptivePresentationControllerDelegate
extension SlideInPresentationManager: UIAdaptivePresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
if traitCollection.verticalSizeClass == .compact && disableCompactHeight {
return .overFullScreen
} else {
return .none
}
}
func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
guard case(.overFullScreen) = style else { return nil }
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "RotateViewController")
}
}
slidein animator:
final class SlideInPresentationAnimator: NSObject {
// MARK: - Properties
let direction: PresentationDirection
let isPresentation: Bool
// MARK: - Initializers
init(direction: PresentationDirection, isPresentation: Bool) {
self.direction = direction
self.isPresentation = isPresentation
super.init()
}
}
// MARK: - UIViewControllerAnimatedTransitioning
extension SlideInPresentationAnimator: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let key = isPresentation ? UITransitionContextViewControllerKey.to : UITransitionContextViewControllerKey.from
let controller = transitionContext.viewController(forKey: key)!
if isPresentation {
transitionContext.containerView.addSubview(controller.view)
}
let presentedFrame = transitionContext.finalFrame(for: controller)
var dismissedFrame = presentedFrame
switch direction {
case .left:
dismissedFrame.origin.x = -presentedFrame.width
case .right:
dismissedFrame.origin.x = transitionContext.containerView.frame.size.width
case .top:
dismissedFrame.origin.y = -presentedFrame.height
case .bottom:
dismissedFrame.origin.y = transitionContext.containerView.frame.size.height
}
let initialFrame = isPresentation ? dismissedFrame : presentedFrame
let finalFrame = isPresentation ? presentedFrame : dismissedFrame
let animationDuration = transitionDuration(using: transitionContext)
controller.view.frame = initialFrame
UIView.animate(withDuration: animationDuration, animations: {
controller.view.frame = finalFrame
}) { finished in
transitionContext.completeTransition(finished)
}
}
}
You can try to subclass UIPresentationController and override var presentedView: UIView? and enforce presentedView's frame.
override var presentedView: UIView? {
super.presentedView?.frame = frameOfPresentedViewInContainerView
return super.presentedView
}
See example: "Custom View Controller Presentation" from Kyle Bashour https://kylebashour.com/posts/custom-view-controller-presentation-tips

iOS: Custom transitioningDelegate doesn't work

This is my custom transitioningDelegate:
enum CameraState {
case On
case Off
}
class CameraTransitioning: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
var state: CameraState
init(state: CameraState) {
self.state = state
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView()
let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)
var toViewInitialFrame = transitionContext.initialFrameForViewController(toVC!)
var fromViewFinalFrame = transitionContext.finalFrameForViewController(fromVC!)
switch self.state {
case .On:
toViewInitialFrame.origin.y = containerView!.frame.height
case .Off:
fromViewFinalFrame.origin.y = -containerView!.frame.height
}
containerView?.addSubview(toView!)
toView?.frame = toViewInitialFrame
let duration = self.transitionDuration(transitionContext)
UIView.animateWithDuration(duration, animations: {
fromView?.frame = fromViewFinalFrame
}) {
finished in
transitionContext.completeTransition(true)
}
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 10
}
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
}
And this is how I use it:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "Home -> Camera" {
let cameraVC = segue.destinationViewController as! CameraViewController
cameraVC.delegate = self
cameraVC.transitioningDelegate = CameraTransitioning(state: .On)
}
}
As you can see, I use this transitioning because I don't like the default UIViewAnimationCurveEaseInOut, and I have tried to set the duration to 10 to make this change clear. But this doesn't work. Where is the problem?
The transitioningDelegate property is weak, and you are creating no other strong references to it. Something else needs to own that object for it to stick around long enough to be used to animate the transition.

Interactive Transition With Push Segue Not Working (Swift)

I'm lost in the universe of the transitions. I want an interactive transition with a push segue. The following code works with a modal segue, but not with a push one :
(With a push segue, the animation is not interactive and is reversed)
FirstViewController.swift
let transitionManager = TransitionManager()
override func viewDidLoad() {
super.viewDidLoad()
transitionManager.sourceViewController = self
// Do any additional setup after loading the view.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
let dest = segue.destinationViewController as UIViewController
dest.transitioningDelegate = transitionManager
transitionManager.destViewController = dest
}
TransitionManager.swift
class TransitionManager: UIPercentDrivenInteractiveTransition,UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate,UIViewControllerInteractiveTransitioning {
var interactive = false
var presenting = false
var panGesture : UIPanGestureRecognizer!
var destViewController : UIViewController!
var sourceViewController : UIViewController! {
didSet {
panGesture = UIPanGestureRecognizer(target: self, action: "gestureHandler:")
sourceViewController.view.addGestureRecognizer(panGesture)
}
}
func gestureHandler(pan : UIPanGestureRecognizer) {
let translation = pan.translationInView(pan.view!)
let velocity = pan.velocityInView(pan.view!)
let d = translation.x / pan.view!.bounds.width * 0.5
switch pan.state {
case UIGestureRecognizerState.Began :
interactive = true
sourceViewController.performSegueWithIdentifier("1to2", sender: self)
case UIGestureRecognizerState.Changed :
self.updateInteractiveTransition(d)
default :
interactive = false
if d > 0.2 || velocity.x > 0 {
self.finishInteractiveTransition()
}
else {
self.cancelInteractiveTransition()
}
}
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
// create a tuple of our screens
let screens : (from:UIViewController, to:UIViewController) = (transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!, transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!)
let container = transitionContext.containerView()
let toView = screens.to.view
let fromView = screens.from.view
toView.frame = CGRectMake(-320, 0, container.frame.size.width, container.frame.size.height)
container.addSubview(toView)
container.addSubview(fromView)
let duration = self.transitionDuration(transitionContext)
// perform the animation!
UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.8, options: nil, animations: {
toView.frame.origin = container.frame.origin
fromView.frame.origin = CGPointMake(320, 0)
}, completion: { finished in
if(transitionContext.transitionWasCancelled()){
transitionContext.completeTransition(false)
UIApplication.sharedApplication().keyWindow.addSubview(screens.from.view)
}
else {
transitionContext.completeTransition(true)
UIApplication.sharedApplication().keyWindow.addSubview(screens.to.view)
}
})
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return 1
}
// MARK: UIViewControllerTransitioningDelegate protocol methods
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = true
return self
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = false
return self
}
func interactionControllerForPresentation(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return self.interactive ? self : nil
}
func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return self.interactive ? self : nil
}
}
Storyboard
The segue is from the FirstViewController to the SecondViewController.
Identifier : "1to2"
Segue : Push
Destination : Current
Thanks for your help

Resources