What is the impact of iOS 7's new swipe-to-pop gesture on the view controller lifecycle of UINavigationController
?

- 4,144
- 24
- 42
3 Answers
New in iOS 7 is a swipe-to-pop gesture in UINavigationController
; you can swipe your finger from left-to-right to do what is normally done with the back button. The thing you have to watch for, is that the pop transition is cancellable.
Tapping the back button still works the way you would expect it to:
- User taps the back button
viewWillDisappear
is calledviewDidDisappear
is called- Popped controller is released
Completing a swipe-to-pop is like tapping the back button
- User begins to swipe from left-to-right
viewWillDisappear
is called- User completes the swipe gesture
viewDidDisappear
is called- Popped controller is released
A cancelled swipe-to-pop works like this
- User begins to swipe from left-to-right
viewWillDisappear
is called- User aborts the swipe gesture (by reversing it, or by not dragging far enough to the right)
viewWillAppear
is calledviewDidAppear
is called
Update your expectations, and your view lifecycle methods accordingly.
Of note is the fact that viewWillDisappear
is called in all cases, even if the user aborts the pop gesture. This may prove be a lie; if the swipe-to-pop gesture is aborted, your view isn't going to disappear, is it?
Like all of us, I strive to balance addObserver/removeObserver
calls in my app to prevent crashes. I override the view controller lifecycle methods viewWillAppear/viewWillDisappear
to do the housekeeping, and maintain a setupPerformed
flag to prevent observers from being added more than once during a view controller's lifetime. Moreover, I have relied on this trick to determine whether a view controller is about to be popped off a navigation controller's stack and subsequently released, so that I can know when precisely to tear down my observers.
iOS 7 has complicated this pattern. I can no longer rely on a view controller being torn down when viewWillDisappear
is called. I have to expect that it might turn around, yell "just kidding," and proceed to call viewWillAppear/viewDidAppear
all over again.

- 1
- 1

- 4,144
- 24
- 42
-
2Yikes! I remove my observers similarly. – HalR Sep 21 '13 at 05:40
-
6Additionally, when you are in the middle of a swipe (a pan) then your UINavigationController will receive a call to -[UINavigationController popViewControllerAnimated:]. But when you cancel the swipe (the pan) by reversing it then you will *not* get a call to -[UINavigationController pushViewController:animated:] – mamills Oct 22 '13 at 17:57
-
4Another thing to note is the same behavior is applied to the (parent) view controller underneath the one you're popping from. The moment it peeks out, `viewWillAppear` is called, and if you cancel the pop, `viewWillDisappear` and `viewDidDisappear` are called respectively. – James Kuang Dec 03 '13 at 21:46
-
4The core lesson is this: on iOS 7 or later, think of `viewWillAppear` as **`viewMightAppear`**, and `viewWillDisappear` as **`viewMightDisappear`**. You may not receive the corresponding `viewDid...` call after receiving the `viewWill...` call, for both the current view controller **and** the previous one in the stack. – smileyborg Feb 27 '14 at 20:45
-
thank you for the insight :) Is there a property for determining the percentage of the swipe in relation to the screenWidth or something similar? Or do I have to track it myself? I want to fade in the navigationBar. – Nick Podratz Aug 09 '15 at 12:44
-
Good question, @NickPodratz! You should ask that as a separate question. – steveluscher Sep 09 '15 at 18:06
-
I dont think Cancelled swipe works as u described anymore, it doesnt seems to get called on viewWillAppear – Tj3n Jun 13 '16 at 07:53
-
@Tj3n: Can you test this on every iOS version since iOS 6 (including the beta of iOS 10) and report back with the version number where the behavior changed? – steveluscher Jun 24 '16 at 16:20
Great post!
As you say, you can no longer use the viewWillDisappear
and the 'trick' as you described, but instead this works fine for me on iOS7 for trapping the back button.
- (void)viewDidDisappear:(BOOL)animated
{
if (self.isMovingFromParentViewController == YES) {
// Do the tidy up as before....
}
}
Hope this helps somebody.

- 4,144
- 24
- 42

- 111
- 2
My situation was slightly different. I'm overriding popViewControllerAnimated in a custom navigationController class. In the popViewControllerAnimated, I was able to detect a pop was occurring via drag when
self.interactivePopGestureRecognizer.state == UIGestureRecognizerStatePossible

- 1,006
- 10
- 13