Domanda

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

È stato utile?

Soluzione

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:

  1. User taps the back button
  2. viewWillDisappear is called
  3. viewDidDisappear is called
  4. Popped controller is released

Completing a swipe-to-pop is like tapping the back button

  1. User begins to swipe from left-to-right
  2. viewWillDisappear is called
  3. User completes the swipe gesture
  4. viewDidDisappear is called
  5. Popped controller is released

A cancelled swipe-to-pop works like this

  1. User begins to swipe from left-to-right
  2. viewWillDisappear is called
  3. User aborts the swipe gesture (by reversing it, or by not dragging far enough to the right)
  4. viewWillAppear is called
  5. viewDidAppear 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.

Altri suggerimenti

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.

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top