90

I am using normal storyboarding and push segues in xcode, but I want to have segues that just appear the next view, not slide the next view (as in when you use a tab bar and the next view just appears).

Is there a nice simple way to have normal push segues just "appear" and not "slide", without needing to add custom segues?

Everything is working completely fine, I just want to remove that slide animation between the views.

R2D2
  • 2,620
  • 4
  • 24
  • 46
  • I have just tried to change the push segue to a modal segue, as that can let me remove the animation, but I have a tableview with a top toolbar, and setting the segue to modal removes this top bar, and I cant find any way to add the top bar back in! So I need a solution that doesnt animate the transition, but doesnt break my tableview. – R2D2 Apr 25 '13 at 14:51

11 Answers11

143

I was able to do this by creating a custom segue (based on this link).

  1. Create a new segue class (see below).
  2. Open your Storyboard and select the segue.
  3. Set the class to PushNoAnimationSegue (or whatever you decided to call it).

Specify segue class in Xcode

Swift 4

import UIKit

/*
 Move to the next screen without an animation.
 */
class PushNoAnimationSegue: UIStoryboardSegue {

    override func perform() {
        self.source.navigationController?.pushViewController(self.destination, animated: false)
    }
}

Objective C

PushNoAnimationSegue.h

#import <UIKit/UIKit.h>

/*
 Move to the next screen without an animation.
 */
@interface PushNoAnimationSegue : UIStoryboardSegue

@end

PushNoAnimationSegue.m

#import "PushNoAnimationSegue.h"

@implementation PushNoAnimationSegue

- (void)perform {

    [self.sourceViewController.navigationController pushViewController:self.destinationViewController animated:NO];
}

@end
Ian
  • 7,480
  • 2
  • 47
  • 51
  • 11
    Best answer. Any ideas on achieving the same for the back-animation? – Thomas Sep 25 '13 at 13:02
  • 1
    Works like a charm. This is also the "correct" way to do it with storyboard segues. – Jeff Richley Dec 06 '13 at 17:52
  • This works great in app, but makes the storyboard look like trash for custom navigation controllers of a small size. Be sure to keep track of how big the content window you're trying to use is so that you can keep the same dimensions. – Josh Lowe Jan 19 '14 at 17:48
  • Bump on the back animation. Who wants animation on pop when you don't on push? – Jonny Feb 20 '14 at 07:43
  • Works like a charm. Thanks alot!! I can't mark this answer as the correct answer for me, but definitely 'upped' it. – Septronic Mar 02 '14 at 23:35
  • 1
    Has any one stopped the back animation for the above answer. – Imran Aug 14 '14 at 09:09
  • THE solution. THX! +1 – HBublitz Aug 22 '14 at 10:52
  • Here is a very nice tutorial with both custom segue and custom unwinding segue: http://blog.dadabeatnik.com/2013/10/13/custom-segues/ – Pedro Borges Oct 02 '14 at 20:23
  • 4
    Not THE solution, the custom segue presents over the whole layout just like a modal push while the original push segue honours window.frame navigationController tabBarController etc... how does one configure the segue to behave like a push segue instead of like a modal segue? or... the $1.000.000 question, how does one specify animations=NO when configuring a regular segue using STORYBOARDS – Pedro Borges Oct 03 '14 at 18:33
  • FWIW, I could achieve a non-animated unwind with this in iOS8 and 9: http://spin.atomicobject.com/2015/03/03/ios-unwind-segue-custom-animation/ – Drakes Oct 23 '15 at 15:18
  • Pedro Borges, read my answer - I linked a tutorial that answers your million dollar question. 2 years late, but still! – Abhi Nov 09 '16 at 05:04
50

You can uncheck "Animates" in Interface Builder for iOS 9

enter image description here

dtochetto
  • 676
  • 6
  • 8
  • 3
    This is the answer to the original question! Other answers show how to achieve this in objc/swift code, while dtochetto uses only Xcode (like requested in the original question). – drpawelo Oct 19 '15 at 14:44
  • however for the unwind segue it doesn't seems to work – Nicolas Manzini Nov 06 '15 at 08:35
  • 2
    This is the best and quickest solution, unfortunately this does not work on iOS 8. – EricH206 Nov 09 '15 at 12:35
  • 2
    @DanielT. Maybe, you can drag 2 segue on storyboard, one has animation, and another has no animation. Give them different `Identifier` name. – AechoLiu Jul 28 '16 at 08:23
  • 1
    Note that XCode just adds an attribute to the segue element in the .storyboard file. You can manually edit the .storyboard file and add animates="NO" to the segues that you care about if you're using visual studio and the checkmark isn't available in the designer. – Wes May 25 '17 at 22:40
35

Ian's answer works great!

Here's a Swift version of the Segue, if anyone needs:

UPDATED FOR SWIFT 5, MAY 2020

PushNoAnimationSegue.swift

import UIKit

/// Move to the next screen without an animation
class PushNoAnimationSegue: UIStoryboardSegue {
override func perform() {
    if let navigation = source.navigationController {
        navigation.pushViewController(destination as UIViewController, animated: false)
    }
}
webo80
  • 3,365
  • 5
  • 35
  • 52
zavié
  • 4,301
  • 2
  • 34
  • 46
  • 2
    Probably due to Swift version, I needed "as!" instead of "as" in the two places you use them. – Carlos Jun 16 '15 at 08:07
  • 1
    Hm maybe in Swift 1.2? I checked with Swift 2.0 in Xcode 7 Beta1 and it compiled without any warnings. – zavié Jun 16 '15 at 13:56
6

I have now managed to do this using the following code:

CreditsViewController *creditspage = [self.storyboard instantiateViewControllerWithIdentifier:@"Credits"];
[UIView beginAnimations:@"flipping view" context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:YES];
[self.navigationController pushViewController:creditspage animated:NO];
[UIView commitAnimations];

Hope this helps someone else!

R2D2
  • 2,620
  • 4
  • 24
  • 46
  • You can just add this to the action of a UIButton or whatever. If you want to jump to a new view controller with no animation, you can use: - void(yourUIButtonAction) { CreditsViewController *creditspage = [self.storyboard instantiateViewControllerWithIdentifier:@"Credits"]; [self.navigationController pushViewController:creditspage animated:NO]; } – R2D2 May 29 '13 at 21:01
  • This is not even answering the question. You aren't using segue here ! – KIDdAe Apr 05 '17 at 13:46
4

Here's the Swift version adapted to modally present a ViewController without animation:

import UIKit

/// Present the next screen without an animation.
class ModalNoAnimationSegue: UIStoryboardSegue {

    override func perform() {
        self.sourceViewController.presentViewController(
            self.destinationViewController as! UIViewController,
            animated: false,
            completion: nil)
    }

}
n.Drake
  • 2,585
  • 2
  • 15
  • 8
Daniel McLean
  • 451
  • 7
  • 10
  • 1
    This code is copied from @zavié answer, not adding anything, but is indeed worse: no check for optionals included – Diego Freniche May 20 '15 at 11:07
  • This is different from @zavié's answer because it shows how to **modally** present a ViewController without animation.Nice to have it here as reference since it's somewhat related to the question. – n.Drake Jul 15 '15 at 06:39
2

answer using Swift3 -

for "push" segue:

class PushNoAnimationSegue: UIStoryboardSegue
{
    override func perform()
    {
       source.navigationController?.pushViewController(destination, animated: false)
    }
}

for "modal" segue:

class ModalNoAnimationSegue: UIStoryboardSegue
{
    override func perform() {
        self.source.present(destination, animated: false, completion: nil)
    }
}
elkorb
  • 151
  • 1
  • 8
1

For anyone using Xamarin iOS your custom segue class needs to look like this:

[Register ("PushNoAnimationSegue")]
public class PushNoAnimationSegue : UIStoryboardSegue
{
    public PushNoAnimationSegue(IntPtr handle) : base (handle)
    {

    }

    public override void Perform ()
    {
        SourceViewController.NavigationController.PushViewController (DestinationViewController, false);
    }
}

Don't forget you still need set a custom segue in your story board and set the class to the PushNoAnimationSegue class.

JacobK
  • 53
  • 8
0

Just set animated false on UINavigationController.pushViewController in Swift

self.navigationController!.pushViewController(viewController, animated: false)
Michael
  • 9,639
  • 3
  • 64
  • 69
0

For me, the easiest way to do so is :

UIView.performWithoutAnimation { 

        self.performSegueWithIdentifier("yourSegueIdentifier", sender: nil)

    }

Available from iOS 7.0

LironXYZ
  • 87
  • 6
  • If using adaptive segues I believe although performWithoutAnimation sets animations disabled, before the segue is performed animations are enabled again if the segue has "animates" checked. After performing, It does however disable them again if previously were. – malhal Nov 20 '19 at 11:32
  • But you can work around it by making a UIStoryboardSegue subclass and disabling animations again before the perform (e.g. using the constructor to check if they are disabled and storing it in a property). – malhal Nov 20 '19 at 12:37
  • I submitted feedback FB11718965 requesting this feature – malhal Oct 25 '22 at 20:20
0

I'm using Visual Studio w/ Xamarin, and the designer doesn't provide the "Animates" checkmark in dtochetto's answer.

Note that the XCode designer will apply the following attribute to the segue element in the .storyboard file: animates="NO"

I manually edited the .storyboard file and added animates="NO" to the segue element(s), and it worked for me.

Example:

 <segue id="1234" destination="ZB0-vP-ctU" kind="modal" modalTransitionStyle="crossDissolve" animates="NO" identifier="screen1ToScreen2"/>
Wes
  • 1,059
  • 13
  • 18
0

PUSH WITHOUT ANIMATION : Swift Here is what worked for me.

import ObjectiveC

private var AssociatedObjectHandle: UInt8 = 0
    extension UIViewController {

        var isAnimationRequired:Bool {
            get {
        return (objc_getAssociatedObject(self, &AssociatedObjectHandle) as? Bool) ?? true
            }
            set {
                objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }

    -------------------- SilencePushSegue --------------------

class SilencePushSegue: UIStoryboardSegue {

    override func perform() {
        if self.source.isAnimationRequired == false {
            self.source.navigationController?.pushViewController(self.destination, animated: false)
        }else{
            self.source.navigationController?.pushViewController(self.destination, animated: true)
        }
    }
}

Usage : Set the segue class from storyboard as shown in picture. set the isAnimationRequired from your viewcontroller to false from where you want to call performSegue, when you want to push segue without animation and set back to true after calling self.performSegue. Best of luck....

DispatchQueue.main.async {
                self.isAnimationRequired = false
                self.performSegue(withIdentifier: "showAllOrders", sender: self);
                self.isAnimationRequired = true
            }

set the segue class from storyboard as shown in picture.

Usman
  • 457
  • 4
  • 8