Dismissing Modal and Current UIViewControllers in the Same Delegate

[banner id=”salesfolio” url=”/sales_folio.pdf”]

Sometimes in iOS, something that seems like it should be easy to do can, be a bit more complicated than you would expect or can be difficult to remember since you don’t do it very often.  This is often the case for me when I have a view controller that presents another view controller modally and then during the delegate callback for the modal, I want to not only dismiss the modal itself, but the current view controller that presented it to begin with.  This post will simply describe how I normally accomplish this task.

First, I present the modal view controller to do whatever task I need it to do.  In this example, I am doing a signature capture:

  1. SignatureViewController *sigViewController = [[SignatureViewController alloc] init];
  2. sigViewController.delegate = self;
  3. sigViewController.modalPresentationStyle = UIModalPresentationFullScreen;
  4. sigViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
  5. [self presentViewController:sigViewController animated:YES completion:NULL];

Then after I collect the signature in the SignatureViewController, I call the appropriate delegate in the original view controller:

  1. if (delegate && [delegate respondsToSelector:@selector(signatureController:signatureAsBase64:savePressed:)]) {
  2.         NSString *signature = [signaturePad getSignatureAsBase64];
  3.         [delegate signatureController:self signatureAsBase64:signature savePressed:sender];
  4. }

All pretty standard fare. Now things get just a little different than normal in the delegate. For this example we will go back to the second view controller in our navigation controller, the first being a login screen that we don’t want the user to repeat.

  1. // It's *VERY* important not to animate this.  Otherwise it causes problems with
  2. // popping back to the lookup screen.  Causes the views to try to
  3. // lay themselves out while being dismissed
  4. __block OrderPickDetailViewController *me = self;
  5. [self dismissViewControllerAnimated:NO completion:^{
  6.         UIViewController *popTo = nil;
  7.         NSArray *viewControllers = [me.navigationController viewControllers];
  8.         if (viewControllers && [viewControllers count] > 1) {
  9.             popTo = [viewControllers objectAtIndex:1];
  10.         }
  11.  
  12.         if (popTo) {
  13.             [me.navigationController popToViewController:popTo animated:YES];
  14.         } else {
  15.             [me.navigationController popToRootViewControllerAnimated:YES];
  16.         }
  17.  
  18. }];

The important things to note here are:

  • Do not animate the dismissal of the modal. Mixing that animation with the dismissal of the current view controller will cause the view to try to lay itself out while it is being released.
  • We use the completion block of the modal dismissal to dismiss the current view controller.
  • I’m holding a block level reference to the current view controller to make sure that I have access to it during the entire time I am setting up the navigation away from the current view controller. As soon as the block goes out of scope, ARC reclaims it and the view controller is released, so we do not have a retain loop.

That’s all there is to it. Generally the biggest thing to remember in these types of situations is not to have two animations going at the same time and to sequence things logically if you can.

About the Author

Steve McCoole profile.

Steve McCoole

Principal Technologist

Steve is a Principal Technologist for Mobile Development at Object Partners where he has been focusing on developing an enterprise mobile development practice, delivering applications to client that include: Oracle Retail, The Tile Shop, St. Jude Medical, SICK USA and Donaldson Corporation.  He has over 32 years of experience developing solutions from embedded, mobile and large-scale Java Enterprise web applications for diverse clients including IBM, Sun, Novell, Best Buy and Thomson Reuters.

One thought on “Dismissing Modal and Current UIViewControllers in the Same Delegate

  1. Ahmed says:

    Hey,

    Thanks for the detailed explanation. I’m trying to do the same thing and it works, but for reason a gap appears after the navigationBar in the rootViewController.

    It’s too long to explain it on here. I have posted the question on StackOverFlow. Thanks!

Leave a Reply

Your email address will not be published.

Related Blog Posts
Building Better Data Visualization Experiences: Part 1 of 2
Through direct experience with data scientists, business analysts, lab technicians, as well as other UX professionals, I have found that we need a better understanding of the people who will be using our data visualization products in order to build them. Creating a product utilizing data with the goal of providing insight is fundamentally different from a typical user-centric web experience, although traditional UX process methods can help.
Kafka Schema Evolution With Java Spring Boot and Protobuf
In this blog I will be demonstrating Kafka schema evolution with Java, Spring Boot and Protobuf.  This app is for tutorial purposes, so there will be instances where a refactor could happen. I tried to […]
Redis Bitmaps: Storing state in small places
Redis is a popular open source in-memory data store that supports all kinds of abstract data structures. In this post and in an accompanying example Java project, I am going to explore two great use […]
Let’s build a WordPress & Kernel updated AMI with Packer
First, let’s start with What is an AMI? An Amazon Machine Image (AMI) is a master image for the creation of virtual servers in an AWS environment. The machine images are like templates that are configured with […]