Skip to content

Instantly share code, notes, and snippets.

@jpmhouston
Last active December 20, 2015 10:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpmhouston/6118713 to your computer and use it in GitHub Desktop.
Save jpmhouston/6118713 to your computer and use it in GitHub Desktop.
PushPopNotifyingNavigationController. Add new notifications to UINavigationController, for when interested in when a view is specifically pushed or popped, instead of the normal delegate method which are called when views are revealed in either manner indistinguishably.
//
// PushPopNotifyingNavigationController.h
//
//
// Created by Pierre Houston on 2013-07-29.
//
// Add new notifications to UINavigationController, for when interested in when a
// view is specifically pushed or popped, instead of the normal delegate method
// which are called when views are revealed in either manner indistinguishably.
#import <UIKit/UIKit.h>
@interface PushPopNotifyingNavigationController : UINavigationController
// the previously shown view controller, nil when first opened, o/w the parent when pushed, or the just popped child
@property (nonatomic, readonly) UIViewController *previousViewController;
@end
@protocol PushPopNotifyingNavigationControllerDelegate <UINavigationControllerDelegate>
@optional
- (void)navigationController:(UINavigationController *)navigationController willPushViewController:(UIViewController *)pushedViewController;
- (void)navigationController:(UINavigationController *)navigationController willPushViewController:(UIViewController *)pushedViewController onto:(UIViewController *)coverredViewController;
- (void)navigationController:(UINavigationController *)navigationController willPopViewController:(UIViewController *)poppedViewController;
- (void)navigationController:(UINavigationController *)navigationController willPopViewController:(UIViewController *)poppedViewController backTo:(UIViewController *)revealedViewController;
- (void)navigationController:(UINavigationController *)navigationController isPoppingViewController:(UIViewController *)poppedViewController;
- (void)navigationController:(UINavigationController *)navigationController isPoppingViewController:(UIViewController *)poppedViewController backTo:(UIViewController *)revealedViewController;
@end
//
// PushPopNotifyingNavigationController.m
//
//
// Created by Pierre Houston on 2013-07-29.
//
// Add new notifications to UINavigationController, see http://stackoverflow.com/questions/642312/
// To do: also override popToViewController:animated & popToRootViewControllerAnimated:
#import "PushPopNotifyingNavigationController.h"
@implementation PushPopNotifyingNavigationController
static id previousViewControllerAssociatedObjectKey;
- (UIViewController *)previousViewController {
UIViewController *previousViewController = objc_getAssociatedObject(self, &previousViewControllerAssociatedObjectKey);
return previousViewController;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
BOOL delegateConforms = [self.delegate conformsToProtocol:@protocol(PushPopNotifyingNavigationControllerDelegate)];
UIViewController *previousViewController = self.topViewController;
objc_setAssociatedObject(self, &previousViewControllerAssociatedObjectKey, previousViewController, OBJC_ASSOCIATION_ASSIGN);
if (delegateConforms && [self.delegate respondsToSelector:@selector(navigationController:willPushViewController:)])
[(id<PushPopNotifyingNavigationControllerDelegate>)self.delegate navigationController:self willPushViewController:viewController];
if (delegateConforms && [self.delegate respondsToSelector:@selector(navigationController:willPushViewController:onto:)])
[(id<PushPopNotifyingNavigationControllerDelegate>)self.delegate navigationController:self willPushViewController:viewController onto:previousViewController];
[super pushViewController:viewController animated:animated];
}
- (UIViewController *)popViewControllerAnimated:(BOOL)animated {
BOOL delegateConforms = [self.delegate conformsToProtocol:@protocol(PushPopNotifyingNavigationControllerDelegate)];
UIViewController *restoringViewController = (self.viewControllers.count >= 2) ? [self.viewControllers objectAtIndex:self.viewControllers.count - 2] : nil; // one back from the end
UIViewController *poppedViewController = self.topViewController;
objc_setAssociatedObject(self, &previousViewControllerAssociatedObjectKey, poppedViewController, OBJC_ASSOCIATION_ASSIGN);
if (delegateConforms && [self.delegate respondsToSelector:@selector(navigationController:willPopViewController:)])
[(id<PushPopNotifyingNavigationControllerDelegate>)self.delegate navigationController:self willPopViewController:poppedViewController];
if (delegateConforms && [self.delegate respondsToSelector:@selector(navigationController:willPopViewController:backTo:)])
[(id<PushPopNotifyingNavigationControllerDelegate>)self.delegate navigationController:self willPopViewController:poppedViewController backTo:restoringViewController];
UIViewController *result = [super popViewControllerAnimated:animated];
if (delegateConforms && [self.delegate respondsToSelector:@selector(navigationController:isPoppingViewController:)])
[(id<PushPopNotifyingNavigationControllerDelegate>)self.delegate navigationController:self isPoppingViewController:poppedViewController];
if (delegateConforms && [self.delegate respondsToSelector:@selector(navigationController:isPoppingViewController:backTo:)])
[(id<PushPopNotifyingNavigationControllerDelegate>)self.delegate navigationController:self isPoppingViewController:poppedViewController backTo:restoringViewController];
return result;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment