├── DMGesturedNavigationController ├── en.lproj │ ├── InfoPlist.strings │ └── ViewController.xib ├── Default.png ├── Default@2x.png ├── Default-568h@2x.png ├── WithinNavigationViewController.h ├── ChoiceViewController.h ├── main.m ├── DMGesturedNavigationController-Prefix.pch ├── AppDelegate.h ├── ViewController.h ├── DMGesturedNavigationController-Info.plist ├── WithinNavigationViewController.m ├── AppDelegate.m ├── ChoiceViewController.m ├── ViewController.m └── ChoiceViewController.xib ├── .gitignore ├── README.md ├── Classes ├── DMGesturedNavigationController.h └── DMGesturedNavigationController.m └── DMGesturedNavigationController.xcodeproj └── project.pbxproj /DMGesturedNavigationController/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dimillian/DMGesturedNavigationController/master/DMGesturedNavigationController/Default.png -------------------------------------------------------------------------------- /DMGesturedNavigationController/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dimillian/DMGesturedNavigationController/master/DMGesturedNavigationController/Default@2x.png -------------------------------------------------------------------------------- /DMGesturedNavigationController/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dimillian/DMGesturedNavigationController/master/DMGesturedNavigationController/Default-568h@2x.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/WithinNavigationViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WithinNavigationViewController.h 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 5/7/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WithinNavigationViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/ChoiceViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ChoiceViewController.h 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 5/7/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ChoiceViewController : UIViewController 12 | 13 | - (IBAction)onFreeNavigation:(id)sender; 14 | - (IBAction)onLockedStack:(id)sender; 15 | @end 16 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 04/05/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/DMGesturedNavigationController-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'DMGesturedNavigationController' target in the 'DMGesturedNavigationController' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 04/05/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ViewController; 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 04/05/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DMGesturedNavigationController.h" 11 | 12 | @interface ViewController : UIViewController 13 | - (IBAction)onHideNavBar:(id)sender; 14 | - (IBAction)onRemove:(id)sender; 15 | - (IBAction)onInsert:(id)sender; 16 | - (IBAction)onPushNew:(id)sender; 17 | - (IBAction)onPushNewVC:(id)sender; 18 | - (IBAction)pushVC:(id)sender; 19 | @property (weak, nonatomic) IBOutlet UIButton *pushNewVC; 20 | @end 21 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/DMGesturedNavigationController-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.thomasricouard.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/WithinNavigationViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WithinNavigationViewController.m 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 5/7/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import "WithinNavigationViewController.h" 10 | #import "DMGesturedNavigationController.h" 11 | 12 | @interface WithinNavigationViewController () 13 | 14 | @end 15 | 16 | @implementation WithinNavigationViewController 17 | 18 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 19 | { 20 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 21 | if (self) { 22 | // Custom initialization 23 | } 24 | return self; 25 | } 26 | 27 | - (void)viewWillAppear:(BOOL)animated 28 | { 29 | [self.navigationController setNavigationBarHidden:NO animated:YES]; 30 | } 31 | 32 | -(void)viewDidAppear:(BOOL)animated 33 | { 34 | 35 | } 36 | 37 | - (void)viewWillDisappear:(BOOL)animated 38 | { 39 | [self.navigationController setNavigationBarHidden:YES animated:YES]; 40 | } 41 | 42 | - (void)viewDidDisappear:(BOOL)animated 43 | { 44 | 45 | } 46 | 47 | 48 | - (void)viewDidLoad 49 | { 50 | [super viewDidLoad]; 51 | [self.view setBackgroundColor:[UIColor whiteColor]]; 52 | self.title = @"Normal navigation controller"; 53 | // Do any additional setup after loading the view. 54 | } 55 | 56 | - (void)push 57 | { 58 | 59 | } 60 | 61 | - (void)didReceiveMemoryWarning 62 | { 63 | [super didReceiveMemoryWarning]; 64 | // Dispose of any resources that can be recreated. 65 | } 66 | 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 04/05/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "ViewController.h" 12 | #import "DMGesturedNavigationController.h" 13 | #import "WithinNavigationViewController.h" 14 | #import "ChoiceViewController.h" 15 | 16 | @implementation AppDelegate 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 21 | ChoiceViewController *choiceVC = [[ChoiceViewController alloc]initWithNibName:@"ChoiceViewController" bundle:nil]; 22 | // Override point for customization after application launch. 23 | self.window.rootViewController = choiceVC; 24 | [self.window makeKeyAndVisible]; 25 | return YES; 26 | } 27 | 28 | - (void)applicationWillResignActive:(UIApplication *)application 29 | { 30 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 31 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 32 | } 33 | 34 | - (void)applicationDidEnterBackground:(UIApplication *)application 35 | { 36 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 38 | } 39 | 40 | - (void)applicationWillEnterForeground:(UIApplication *)application 41 | { 42 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 43 | } 44 | 45 | - (void)applicationDidBecomeActive:(UIApplication *)application 46 | { 47 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 48 | } 49 | 50 | - (void)applicationWillTerminate:(UIApplication *)application 51 | { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/ChoiceViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ChoiceViewController.m 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 5/7/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import "ChoiceViewController.h" 10 | #import "ViewController.h" 11 | #import "DMGesturedNavigationController.h" 12 | #import "WithinNavigationViewController.h" 13 | 14 | @interface ChoiceViewController () 15 | 16 | @end 17 | 18 | @implementation ChoiceViewController 19 | 20 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 21 | { 22 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 23 | if (self) { 24 | // Custom initialization 25 | } 26 | return self; 27 | } 28 | 29 | - (void)viewDidLoad 30 | { 31 | [super viewDidLoad]; 32 | // Do any additional setup after loading the view from its nib. 33 | } 34 | 35 | - (void)didReceiveMemoryWarning 36 | { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | - (IBAction)onFreeNavigation:(id)sender { 42 | 43 | ViewController *controller1 = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 44 | [controller1.view setBackgroundColor:[UIColor blueColor]]; 45 | ViewController *controller2 = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 46 | [controller2.view setBackgroundColor:[UIColor redColor]]; 47 | ViewController *controller3 = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 48 | [controller3.view setBackgroundColor:[UIColor greenColor]]; 49 | ViewController *controller4 = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 50 | [controller4.view setBackgroundColor:[UIColor orangeColor]]; 51 | 52 | DMGesturedNavigationController *container = 53 | [[DMGesturedNavigationController alloc]initWithViewControllers: 54 | @[controller1, controller2, controller3, controller4]]; 55 | 56 | UINavigationController *navigation = [[UINavigationController alloc]initWithRootViewController:container]; 57 | [container.view setBackgroundColor:[UIColor scrollViewTexturedBackgroundColor]]; 58 | [container setAnimatedNavbarChange:NO]; 59 | [navigation setNavigationBarHidden:YES animated:NO]; 60 | [self presentViewController:navigation animated:YES completion:^{ 61 | 62 | }]; 63 | } 64 | 65 | - (IBAction)onLockedStack:(id)sender { 66 | ViewController *controller1 = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 67 | [controller1.view setBackgroundColor:[UIColor blueColor]]; 68 | controller1.title = @"First"; 69 | 70 | DMGesturedNavigationController *container = 71 | [[DMGesturedNavigationController alloc]initWithViewControllers:@[controller1]]; 72 | 73 | UINavigationController *navigation = [[UINavigationController alloc]initWithRootViewController:container]; 74 | [container.view setBackgroundColor:[UIColor scrollViewTexturedBackgroundColor]]; 75 | [container setAnimatedNavbarChange:YES]; 76 | [container setStackType:DMGesturedNavigationControllerStackLikeNavigationController]; 77 | [navigation setNavigationBarHidden:YES animated:NO]; 78 | [container setPopAnimationType:DMGesturedNavigationControllerPopAnimationClassic]; 79 | [self presentViewController:navigation animated:YES completion:^{ 80 | 81 | }]; 82 | } 83 | @end 84 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 04/05/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "WithinNavigationViewController.h" 11 | 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad 19 | { 20 | [super viewDidLoad]; 21 | UIBarButtonItem *item = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(onBarbuttonItem)]; 22 | self.navigationItem.rightBarButtonItem = item; 23 | // Do any additional setup after loading the view, typically from a nib. 24 | } 25 | 26 | - (void)onBarbuttonItem 27 | { 28 | [self.gesturedNavigationController.parentViewController dismissViewControllerAnimated:YES completion:^{ 29 | 30 | }]; 31 | } 32 | 33 | - (void)didReceiveMemoryWarning 34 | { 35 | [super didReceiveMemoryWarning]; 36 | // Dispose of any resources that can be recreated. 37 | } 38 | 39 | - (void)childViewControllerdidBecomeActive 40 | { 41 | NSLog(@"View Controller %d: Became active", [self gesturedNavigationControllerOffset]); 42 | } 43 | 44 | - (void)childViewControllerdidResignActive 45 | { 46 | NSLog(@"View Controller %d: Resigned active", [self gesturedNavigationControllerOffset]); 47 | } 48 | 49 | - (void)childViewControllerdidShow 50 | { 51 | NSLog(@"View Controller %d: Did show", [self gesturedNavigationControllerOffset]); 52 | self.title = [NSString stringWithFormat:@"VC: %d", [self gesturedNavigationControllerOffset]]; 53 | } 54 | 55 | - (void)childViewControllerdidHide 56 | { 57 | NSLog(@"View Controller %d: Became active", [self gesturedNavigationControllerOffset]); 58 | } 59 | 60 | - (void)childViewControllerCouldBecomeActive 61 | { 62 | NSLog(@"View Controller %d: Could become active", [self gesturedNavigationControllerOffset]); 63 | //Good idea to customize transition 64 | /* 65 | [UIView animateWithDuration:0.30 animations:^{ 66 | [self.view setAlpha:1.0]; 67 | }]; 68 | */ 69 | } 70 | 71 | - (void)childViewControllerCouldBecomeInactive 72 | { 73 | NSLog(@"View Controller %d: Could become innactive", [self gesturedNavigationControllerOffset]); 74 | /* 75 | [UIView animateWithDuration:0.30 animations:^{ 76 | [self.view setAlpha:0.50]; 77 | }]; 78 | */ 79 | } 80 | 81 | - (void)childViewControllerVisiblePartDidChange:(NSNumber *)visiblePartWidth 82 | { 83 | NSLog(@"View controller %d: Visible width %f", [self gesturedNavigationControllerOffset], visiblePartWidth.floatValue ); 84 | } 85 | 86 | - (IBAction)onHideNavBar:(id)sender { 87 | [self.gesturedNavigationController 88 | setNavigationBarHidden:!self.gesturedNavigationController.isNavigatioNBarHidden 89 | animated:YES]; 90 | } 91 | 92 | - (IBAction)onRemove:(id)sender { 93 | [self.gesturedNavigationController removeViewController:self animated:YES]; 94 | } 95 | 96 | - (IBAction)onInsert:(id)sender { 97 | ViewController *controller = [[ViewController alloc]initWithNibName:@"ViewController" bundle:nil]; 98 | [controller.view setBackgroundColor:[UIColor darkGrayColor]]; 99 | [self.gesturedNavigationController inserViewController:controller atStackOffset:2 animated:YES]; 100 | } 101 | 102 | - (IBAction)onPushNew:(id)sender { 103 | ViewController *controller = [[ViewController alloc]initWithNibName:@"ViewController" bundle:nil]; 104 | [controller.view setBackgroundColor:[UIColor darkGrayColor]]; 105 | [self.gesturedNavigationController pushViewController:controller animated:YES removeInBetweenViewControllers:NO]; 106 | } 107 | 108 | - (IBAction)onPushNewVC:(id)sender { 109 | ViewController *controller = [[ViewController alloc]initWithNibName:@"ViewController" bundle:nil]; 110 | [controller.view setBackgroundColor:[UIColor darkGrayColor]]; 111 | [self.gesturedNavigationController pushViewController:controller animated:YES]; 112 | } 113 | 114 | - (IBAction)pushVC:(id)sender { 115 | 116 | WithinNavigationViewController *vc = [[WithinNavigationViewController alloc]initWithNibName:nil bundle:nil]; 117 | [self.gesturedNavigationController.navigationController pushViewController:vc animated:YES]; 118 | } 119 | @end 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DMGesturedNavigationController 2 | ============================== 3 | 4 | Beta: This is a very early release, refactors and more features, less bug too… are coming. 5 | 6 | Feedbacks would be appreciated. 7 | 8 | UINavigationController re-implementation the way Apple should have made it. 9 | Full gesture support for transition and navigation. With stack options and more 10 | 11 | ##Features 12 | 1. Support swipe gesture to navigation between child view controllers 13 | 2. Support both standard UINavigationController stack and a new one where you can navigate back and forth. 14 | 3. Full re-implementation of UINavigationController by subclassing UIViewController. 15 | 4. Provide a protocol for you to know when your view controller are visible, active, etc… 16 | 5. Far more to come. 17 | 18 | 19 | ##How to use it 20 | 21 | Add the files from **/classes** to your project, import `DMGesturedNavigationController` and you're done. 22 | 23 | It works like a UINavigationController, but it's not, it offer various other feature and powerful manipulation of the child view controller stack. 24 | 25 | ###Important 26 | 27 | Take a look at the stackType property, it takes a `DMGesturedNavigationControllerStackType` option 28 | By default it is set to the new `DMGesturedNavigationControllerStackNavigationFree` 29 | `DMGesturedNavigationControllerStackNavigationFree`: Here the user can go back and forth between view controller (like it is actual pages of a book). 30 | 31 | When you go back from a view controller it won't be removed from the hierarchy. You will still be able to navigate to it. 32 | 33 | `DMGesturedNavigationControllerStackLikeNavigationController` work like a classic UINavigationController, if you go back, the previous view controller is removed from the hierarchy. 34 | 35 | ###Classic 36 | 37 | You'll find the usual suspect 38 | 39 | 40 | - (void)pushViewController:(UIViewController *)viewController 41 | animated:(BOOL)animated; 42 | - (void)popViewConrollerAnimated:(BOOL)animated; 43 | - (void)popToRootViewControllerAnimated:(BOOL)animated; 44 | - (void)setNavigationBarHidden:(BOOL)navigationBarHidden animated:(BOOL)animated; 45 | 46 | Which act the same if you are in `DMGesturedNavigationControllerStackLikeNavigationController` mode 47 | 48 | ###New 49 | 50 | To accomodate with the new navigation mode I've added a few other method 51 | 52 | 53 | - (void)pushViewController:(UIViewController *)viewController 54 | animated:(BOOL)animated 55 | removeInBetweenViewControllers:(BOOL)removeInBetweenVC; 56 | 57 | This one is interesting, you can push a new UIViewController and navigate to it, if you set removeInBetweenVC to No, it will preserve view controller betweeen the new pushed one and the last visible one you navigate from. 58 | 59 | - (void)inserViewController:(UIViewController *)viewController 60 | atStackOffset:(NSInteger)offset 61 | animated:(BOOL)animated; 62 | - (void)removeViewController:(UIViewController *)viewControlller 63 | animated:(BOOL)animated; 64 | - (void)navigateToViewController:(UIViewController *)viewController 65 | animated:(BOOL)animated; 66 | - (BOOL)containViewController:(UIViewController *)viewController; 67 | 68 | Those methods are documented. 69 | The new thing is that you can freely add or remove a VC in the stack and navigate to it. 70 | 71 | ###DMGesturedChildViewControllerNotifications 72 | 73 | 74 | DMGesturedNavigationController provide a protocol for you to implement if you wish. 75 | You can implement the methods provided by this protocol, so you will be notified at the right time 76 | when your view controller become active, resign active etc… 77 | 78 | You Should use thode methods instead of Apple one (viewDidAppear…) when working with a DMGesturedNavigationController. 79 | 80 | ##Know issues 81 | 1. The navigation bar stack is bugged when animated if you do too much transitions simultaneously. 82 | 3. The bottom toolbar is not implemented. 83 | 84 | ##License 85 | Copyright (C) 2012 by Thomas Ricouard. 86 | 87 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 88 | 89 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 90 | 91 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Classes/DMGesturedNavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DMGesturedNavigationController.h 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 04/05/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | Type of stack available 13 | DMGesturedNavigationControllerStackNavigationFree The user can freely go back and forth in the stack, 14 | child view controller will never be removed from the stack, only when you push a new one with the flag 15 | DMGesturedNavigationControllerStackLikeNavigationController The stack will work like a standard 16 | UINavigationController, once the user go back in the stack, the last child view controller displayed 17 | will be removed from the hierarchy (and released) 18 | */ 19 | typedef NS_ENUM(NSInteger, DMGesturedNavigationControllerStackType) { 20 | DMGesturedNavigationControllerStackNavigationFree, 21 | DMGesturedNavigationControllerStackLikeNavigationController 22 | }; 23 | 24 | /** 25 | Animation to use when you pop or delete a UIViewController 26 | By default it use the a new custom animation, but you can set it to the classic one 27 | */ 28 | typedef NS_ENUM(NSInteger, DMGesturedNavigationControllerPopRemoveAnimation){ 29 | DMGesturedNavigationControllerPopAnimationClassic, 30 | DMGesturedNavigationControllerPopAnimationNewWay 31 | }; 32 | 33 | /** 34 | DMGesturedChildViewControllerNotifications, you can implement this protocol in your UIViewController subclass 35 | which are used in a DMGesturedNavigationController. If implemented those methods will be called by 36 | DMGesturedNavigationController to notify your UIViewController about it's current state 37 | Do not to call super. 38 | You should use these methods instead of viewDidAppear and viewWillAppear. DMGesturedViewController does not 39 | guarantee to call them only once. Those method will only be called at the right time. 40 | */ 41 | @protocol DMGesturedChildViewControllerNotifications 42 | @optional 43 | /** 44 | Called when your view controller did show. Only called once until it hide. 45 | */ 46 | - (void)childViewControllerdidShow; 47 | /** 48 | Called when your view controller did hide. Only called once until it hide. 49 | */ 50 | - (void)childViewControllerdidHide; 51 | /** 52 | Called when your view controller become active. An active state is when the user effectively ended the 53 | swipe transition gesture and transition animations are done. 54 | */ 55 | - (void)childViewControllerdidBecomeActive; 56 | /** 57 | Called when your view controller become inactive. An inactive your when the view controller is not visible anymore and that gesture and transition animations are ended. 58 | */ 59 | - (void)childViewControllerdidResignActive; 60 | /** 61 | Called when your view controller could become the next active one. When the user scrolled more than 50% of it 62 | Don't assume that it will the active one. 63 | */ 64 | - (void)childViewControllerCouldBecomeActive; 65 | /** 66 | Called when your view controller could become the inactive. When the user scrolled more than 50% out of it 67 | Don't assume that it will the next inactive one. 68 | */ 69 | - (void)childViewControllerCouldBecomeInactive; 70 | /** 71 | Called when a view controller move. Provide you the actual visible width float value wrapped in an NSNumber 72 | It is not called if the view controller is not visible 73 | For example, on an iPhone, if your view controller is full screen, this values can vary from 0.0 to 320.0. 74 | */ 75 | - (void)childViewControllerVisiblePartDidChange:(NSNumber *)visiblePartWidth; 76 | 77 | /** 78 | If you implement this you have a chance to set the title of your root view controller only once 79 | you parent DMGesturedNavigationController is ready. 80 | */ 81 | - (void)childViewControllerCouldProvideTitle; 82 | @end 83 | 84 | @interface DMGesturedNavigationController : UIViewController 85 | 86 | /** 87 | Child view controllers can be swapped at any time by setting this property to a new value. 88 | The view controllers currently on the navigation stack. 89 | The root view controller is at index 0 in the array, the back view controller is at index n-2, and the top controller is at index n-1, where n is the number of items in the array. 90 | */ 91 | @property (nonatomic, strong) NSArray *viewControllers; 92 | /** 93 | The view controller at the top of the navigation stack 94 | */ 95 | @property (nonatomic, readonly, strong) UIViewController *topViewController; 96 | /** 97 | The view controller associated with the currently visible view in the navigation interface 98 | */ 99 | @property (nonatomic, readonly, strong) UIViewController *visibleViewController; 100 | /** 101 | The navigation bar managed by the gestured navigation controller. 102 | */ 103 | @property (nonatomic, readonly, strong) UINavigationBar *navigationBar; 104 | /** 105 | If you set this property to a UIBarButtonItem it will be used as a back button, the action and target 106 | will be set internally you can leave them to nil 107 | You can also implement a UILeftBarButtonItem in your UIViewController navigation item, in this case 108 | no back bar button item will be provided. 109 | */ 110 | @property (nonatomic, strong) UIBarButtonItem *customBackButtonItem; 111 | /** 112 | The stack type, refer to DMGesturedNavigationControllerStackType enum for detail 113 | */ 114 | @property (nonatomic) DMGesturedNavigationControllerStackType stackType; 115 | /** 116 | The pop animation, refer to DMGesturedNavigationControllerPopRemoveAnimation enum for detail 117 | */ 118 | @property (nonatomic) DMGesturedNavigationControllerPopRemoveAnimation popAnimationType; 119 | /** 120 | A Boolean value that determines whether the navigation bar is hidden. 121 | If YES, the navigation bar is hidden. 122 | The default value is NO. Setting this property does not animate the hiding or showing of the navigation bar; 123 | use setNavigationBarHidden:animated: for that purpose. 124 | */ 125 | @property (nonatomic, getter = isNavigatioNBarHidden) BOOL navigationBarHidden; 126 | /** 127 | Set to NO if you don't want the user to be able to do a bounce gesture. 128 | Default value is YES. 129 | */ 130 | @property (nonatomic, getter = isAllowSideBouncing) BOOL allowSideBoucing; 131 | /* 132 | Set to NO if you want to disable the primary feature of this class and be left with a buggy 133 | UINavigationController implementation :) . 134 | Default value is YES. 135 | */ 136 | @property (nonatomic, getter = isAllowSwipeTransition) BOOL allowSwipeTransition; 137 | /* 138 | Set to NO if you don't want to animate the UINavigationItem pop and push of the navigation bar. 139 | You might set it to NO before doing intensive modification of the stack which could lead to a break 140 | of the UINavigationBar stack. DMGesturedNavigationController will always try to rebuild it if corrupted. 141 | Default value is YES. 142 | */ 143 | @property (nonatomic, getter = isAnimatedNavbarChange) BOOL animatedNavbarChange; 144 | 145 | /* 146 | Set to NO if you don't want shadow for the first and the last view controller when the user can scroll the view 147 | over the edge 148 | Default value is YES. 149 | */ 150 | @property (nonatomic, getter = isDisplayEdgeShadow) BOOL displayEdgeShadow; 151 | 152 | /* 153 | Set the background color of DMGesturedNavigationController 154 | You can see the background color when you scroll over the dge 155 | */ 156 | @property (nonatomic, strong) UIColor *backgroundColor; 157 | 158 | /* 159 | Scale animation when a view controller is swiped 160 | Default value is NO 161 | */ 162 | @property (nonatomic, getter = isScalingWhenSwipe) BOOL scalingWhenSwipe; 163 | 164 | /* 165 | if scalingWhenSwipe is set to YES then you can set the minimum scale 166 | Default value is 0.8f 167 | */ 168 | @property (nonatomic) CGFloat minimumScaleOnSwipe; 169 | 170 | /* 171 | Rotate the Y axis when a view controller is swiped 172 | Default value is NO 173 | */ 174 | @property (nonatomic, getter = isRotateYAxisWhenSwipe) BOOL rotateYAxisWhenSwipe; 175 | 176 | /* 177 | if scalingWhenSwipe is set to YES then you can set the mximum inclinaison angle 178 | Default value is 10 179 | */ 180 | @property (nonatomic) CGFloat maximumInclinaisonAngle; 181 | 182 | - (id)initWithRootViewController:(UIViewController *)rootViewController; 183 | - (id)initWithViewControllers:(NSArray *)viewControllers; 184 | 185 | /** 186 | Pushes a view controller onto the receiver’s stack and updates the display. 187 | Remove every view controllers between the current one and the newly pushed one. 188 | @param viewController the view controller to be pushed. 189 | @param animated set YES if you want an transition animation. 190 | */ 191 | - (void)pushViewController:(UIViewController *)viewController 192 | animated:(BOOL)animated; 193 | /** 194 | Pushes a view controller onto the receiver’s stack and updates the display. 195 | @param viewController the view controller to be pushed. 196 | @param animated set YES if you want an transition animation. 197 | @param removeInBetweenVC Is you are in a stackType DMGesturedNavigationControllerStackNavigationFree it is 198 | possible that the visible view controller is not the last one the stack. 199 | Set YES if you want to remove every view controllers between the new one you wan to push and the visible one 200 | Set NO if you don't want to remove in between VC, the passed view controller will be added at the end and displayed. 201 | If your stack type is set to DMGesturedNavigationControllerStackLikeNavigationController this parameter will have no 202 | effect 203 | */ 204 | - (void)pushViewController:(UIViewController *)viewController 205 | animated:(BOOL)animated 206 | removeInBetweenViewControllers:(BOOL)removeInBetweenVC; 207 | 208 | /** 209 | Insert the passed view controller at the specified offset, preserve the stack in between, after and before. 210 | */ 211 | - (void)inserViewController:(UIViewController *)viewController 212 | atStackOffset:(NSInteger)offset 213 | animated:(BOOL)animated; 214 | /** 215 | Remove the passed view controller (if present) from the stack, navigate to the previous view controller 216 | You cannot remove the root view controller 217 | */ 218 | - (void)removeViewController:(UIViewController *)viewControlller 219 | animated:(BOOL)animated; 220 | 221 | /** 222 | Pops the top view controller from the navigation stack and updates the display. 223 | @param animated 224 | Set this value to YES to animate the transition. Pass NO if you are setting up a navigation controller 225 | before its view is displayed. 226 | If your stackType is in DMGesturedNavigationControllerStackLikeNavigationController the previous view controller 227 | will be removed from the stack. 228 | If your top view controller is the root of the stack this method does nothing 229 | */ 230 | 231 | - (void)popViewControllerAnimated:(BOOL)animated; 232 | /** 233 | Pops all the view controllers on the stack except the root view controller and updates the display. 234 | View controller will be removed from the stack only if the stack type is set to 235 | DMGesturedNavigationControllerStackLikeNavigationController 236 | @param Animated pass yes if you want the transition to be animated 237 | */ 238 | - (void)popToRootViewControllerAnimated:(BOOL)animated; 239 | /* 240 | Navigate to the specified view controller 241 | @param viewController Can't be nil, will trigger an assert error if not in the stack or nil 242 | @param animated Specify YES if you want the transition to the new ViewController animated. 243 | */ 244 | - (void)navigateToViewController:(UIViewController *)viewController animated:(BOOL)animated; 245 | /** 246 | @param hidden 247 | Specify YES to hide the navigation bar or NO to show it. 248 | @param animated 249 | Specify YES if you want to animate the change in visibility or 250 | NO if you want the navigation bar to appear immediately. 251 | */ 252 | - (void)setNavigationBarHidden:(BOOL)navigationBarHidden animated:(BOOL)animated; 253 | /** 254 | @param viewController 255 | Pass the view controller which you want to know if it is a child view controller or not. 256 | @return YES if present in the stack, NO if not present. 257 | */ 258 | - (BOOL)containViewController:(UIViewController *)viewController; 259 | 260 | /** 261 | @return the standard UINavigationBar height regarding the iOS version. 262 | If iOS 6 the returned height is 44.0f, if iOS 7+, the returned value is 64.0f 263 | */ 264 | + (CGFloat)standardNavBarHeight; 265 | @end 266 | 267 | /** 268 | Category that can be used if you are in a child view controller UIViewController subclass of 269 | DMGesturedNavigationController. 270 | Provide various useful properties 271 | */ 272 | @interface UIViewController (UIViewControllerGesturedNavigationController) 273 | @property (nonatomic, readonly, weak) DMGesturedNavigationController *gesturedNavigationController; 274 | @property (nonatomic, readonly, weak) UIViewController *previousViewController; 275 | @property (nonatomic, readonly, weak) UIViewController *nextViewController; 276 | @property (nonatomic, readonly) NSInteger gesturedNavigationControllerOffset; 277 | @property (nonatomic, readonly, getter = isVisible) BOOL visible; 278 | @property (nonatomic, readonly, getter = isActive) BOOL active; 279 | - (void)pushViewControllerToSelf; 280 | @end 281 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/ChoiceViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 12D78 6 | 3084 7 | 1187.37 8 | 626.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBNSLayoutConstraint 15 | IBProxyObject 16 | IBUIButton 17 | IBUIView 18 | 19 | 20 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 21 | 22 | 23 | PluginDependencyRecalculationVersion 24 | 25 | 26 | 27 | 28 | IBFilesOwner 29 | IBCocoaTouchFramework 30 | 31 | 32 | IBFirstResponder 33 | IBCocoaTouchFramework 34 | 35 | 36 | 37 | 274 38 | 39 | 40 | 41 | 292 42 | {{2, 113}, {316, 44}} 43 | 44 | 45 | 46 | _NS:9 47 | NO 48 | IBCocoaTouchFramework 49 | 0 50 | 0 51 | 1 52 | Free navigation 53 | 54 | 3 55 | MQA 56 | 57 | 58 | 1 59 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 60 | 61 | 62 | 3 63 | MC41AA 64 | 65 | 66 | 2 67 | 15 68 | 69 | 70 | Helvetica-Bold 71 | 15 72 | 16 73 | 74 | 75 | 76 | 77 | 292 78 | {{0, 218}, {316, 44}} 79 | 80 | 81 | _NS:9 82 | NO 83 | IBCocoaTouchFramework 84 | 0 85 | 0 86 | 1 87 | Locked stack a la UINavigationController 88 | 89 | 90 | 1 91 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 92 | 93 | 94 | 95 | 96 | 97 | 98 | {{0, 20}, {320, 548}} 99 | 100 | 101 | 102 | 103 | 3 104 | MQA 105 | 106 | 2 107 | 108 | 109 | 110 | 111 | IBUIScreenMetrics 112 | 113 | YES 114 | 115 | 116 | 117 | 118 | 119 | {320, 568} 120 | {568, 320} 121 | 122 | 123 | IBCocoaTouchFramework 124 | Retina 4 Full Screen 125 | 2 126 | 127 | IBCocoaTouchFramework 128 | 129 | 130 | 131 | 132 | 133 | 134 | view 135 | 136 | 137 | 138 | 3 139 | 140 | 141 | 142 | onFreeNavigation: 143 | 144 | 145 | 7 146 | 147 | 28 148 | 149 | 150 | 151 | onLockedStack: 152 | 153 | 154 | 7 155 | 156 | 29 157 | 158 | 159 | 160 | 161 | 162 | 0 163 | 164 | 165 | 166 | 167 | 168 | 1 169 | 170 | 171 | 172 | 173 | 5 174 | 0 175 | 176 | 5 177 | 1 178 | 179 | 0.0 180 | 181 | 1000 182 | 183 | 8 184 | 29 185 | 3 186 | 187 | 188 | 189 | 3 190 | 0 191 | 192 | 3 193 | 1 194 | 195 | 218 196 | 197 | 1000 198 | 199 | 3 200 | 9 201 | 3 202 | 203 | 204 | 205 | 9 206 | 0 207 | 208 | 9 209 | 1 210 | 211 | 0.0 212 | 213 | 1000 214 | 215 | 5 216 | 22 217 | 2 218 | 219 | 220 | 221 | 3 222 | 0 223 | 224 | 3 225 | 1 226 | 227 | 113 228 | 229 | 1000 230 | 231 | 3 232 | 9 233 | 3 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | -1 242 | 243 | 244 | File's Owner 245 | 246 | 247 | -2 248 | 249 | 250 | 251 | 252 | 4 253 | 254 | 255 | 256 | 257 | 7 258 | 0 259 | 260 | 0 261 | 1 262 | 263 | 316 264 | 265 | 1000 266 | 267 | 3 268 | 9 269 | 1 270 | 271 | 272 | 273 | 274 | 275 | 11 276 | 277 | 278 | 279 | 280 | 281 | 16 282 | 283 | 284 | 285 | 286 | 22 287 | 288 | 289 | 290 | 291 | 23 292 | 293 | 294 | 295 | 296 | 25 297 | 298 | 299 | 300 | 301 | 27 302 | 303 | 304 | 305 | 306 | 307 | 308 | ChoiceViewController 309 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 310 | UIResponder 311 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 312 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 313 | 314 | 315 | 316 | 317 | 318 | 319 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 320 | 321 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 322 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 323 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 324 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 325 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 326 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 29 337 | 338 | 339 | 340 | 341 | ChoiceViewController 342 | UIViewController 343 | 344 | id 345 | id 346 | 347 | 348 | 349 | onFreeNavigation: 350 | id 351 | 352 | 353 | onLockedStack: 354 | id 355 | 356 | 357 | 358 | IBProjectSource 359 | ./Classes/ChoiceViewController.h 360 | 361 | 362 | 363 | NSLayoutConstraint 364 | NSObject 365 | 366 | IBProjectSource 367 | ./Classes/NSLayoutConstraint.h 368 | 369 | 370 | 371 | 372 | 0 373 | IBCocoaTouchFramework 374 | YES 375 | 3 376 | YES 377 | 2083 378 | 379 | 380 | -------------------------------------------------------------------------------- /DMGesturedNavigationController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 53595AC017392945002CBF6B /* WithinNavigationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53595ABF17392945002CBF6B /* WithinNavigationViewController.m */; }; 11 | 53595AC7173954E0002CBF6B /* ChoiceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53595AC5173954E0002CBF6B /* ChoiceViewController.m */; }; 12 | 53595AC8173954E0002CBF6B /* ChoiceViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 53595AC6173954E0002CBF6B /* ChoiceViewController.xib */; }; 13 | 53595ACA174282A2002CBF6B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53595AC9174282A2002CBF6B /* QuartzCore.framework */; }; 14 | 9F0B625117358ECB00B2AAE9 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F0B625017358ECB00B2AAE9 /* UIKit.framework */; }; 15 | 9F0B625317358ECB00B2AAE9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F0B625217358ECB00B2AAE9 /* Foundation.framework */; }; 16 | 9F0B625517358ECB00B2AAE9 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F0B625417358ECB00B2AAE9 /* CoreGraphics.framework */; }; 17 | 9F0B625B17358ECB00B2AAE9 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9F0B625917358ECB00B2AAE9 /* InfoPlist.strings */; }; 18 | 9F0B625D17358ECB00B2AAE9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F0B625C17358ECB00B2AAE9 /* main.m */; }; 19 | 9F0B626117358ECB00B2AAE9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F0B626017358ECB00B2AAE9 /* AppDelegate.m */; }; 20 | 9F0B626317358ECB00B2AAE9 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 9F0B626217358ECB00B2AAE9 /* Default.png */; }; 21 | 9F0B626517358ECB00B2AAE9 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9F0B626417358ECB00B2AAE9 /* Default@2x.png */; }; 22 | 9F0B626717358ECB00B2AAE9 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9F0B626617358ECB00B2AAE9 /* Default-568h@2x.png */; }; 23 | 9F0B626A17358ECB00B2AAE9 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F0B626917358ECB00B2AAE9 /* ViewController.m */; }; 24 | 9F0B626D17358ECB00B2AAE9 /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9F0B626B17358ECB00B2AAE9 /* ViewController.xib */; }; 25 | 9F0B627617358EEC00B2AAE9 /* DMGesturedNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F0B627517358EEC00B2AAE9 /* DMGesturedNavigationController.m */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 53595ABE17392945002CBF6B /* WithinNavigationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WithinNavigationViewController.h; sourceTree = ""; }; 30 | 53595ABF17392945002CBF6B /* WithinNavigationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WithinNavigationViewController.m; sourceTree = ""; }; 31 | 53595AC4173954E0002CBF6B /* ChoiceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChoiceViewController.h; sourceTree = ""; }; 32 | 53595AC5173954E0002CBF6B /* ChoiceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChoiceViewController.m; sourceTree = ""; }; 33 | 53595AC6173954E0002CBF6B /* ChoiceViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ChoiceViewController.xib; sourceTree = ""; }; 34 | 53595AC9174282A2002CBF6B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 35 | 9F0B624D17358ECB00B2AAE9 /* DMGesturedNavigationController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DMGesturedNavigationController.app; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | 9F0B625017358ECB00B2AAE9 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 37 | 9F0B625217358ECB00B2AAE9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 38 | 9F0B625417358ECB00B2AAE9 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 39 | 9F0B625817358ECB00B2AAE9 /* DMGesturedNavigationController-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DMGesturedNavigationController-Info.plist"; sourceTree = ""; }; 40 | 9F0B625A17358ECB00B2AAE9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 41 | 9F0B625C17358ECB00B2AAE9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 42 | 9F0B625E17358ECB00B2AAE9 /* DMGesturedNavigationController-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DMGesturedNavigationController-Prefix.pch"; sourceTree = ""; }; 43 | 9F0B625F17358ECB00B2AAE9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 44 | 9F0B626017358ECB00B2AAE9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 45 | 9F0B626217358ECB00B2AAE9 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 46 | 9F0B626417358ECB00B2AAE9 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 47 | 9F0B626617358ECB00B2AAE9 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 48 | 9F0B626817358ECB00B2AAE9 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 49 | 9F0B626917358ECB00B2AAE9 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 50 | 9F0B626C17358ECB00B2AAE9 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController.xib; sourceTree = ""; }; 51 | 9F0B627417358EEC00B2AAE9 /* DMGesturedNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DMGesturedNavigationController.h; path = Classes/DMGesturedNavigationController.h; sourceTree = ""; }; 52 | 9F0B627517358EEC00B2AAE9 /* DMGesturedNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DMGesturedNavigationController.m; path = Classes/DMGesturedNavigationController.m; sourceTree = ""; }; 53 | /* End PBXFileReference section */ 54 | 55 | /* Begin PBXFrameworksBuildPhase section */ 56 | 9F0B624A17358ECB00B2AAE9 /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | 53595ACA174282A2002CBF6B /* QuartzCore.framework in Frameworks */, 61 | 9F0B625117358ECB00B2AAE9 /* UIKit.framework in Frameworks */, 62 | 9F0B625317358ECB00B2AAE9 /* Foundation.framework in Frameworks */, 63 | 9F0B625517358ECB00B2AAE9 /* CoreGraphics.framework in Frameworks */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXFrameworksBuildPhase section */ 68 | 69 | /* Begin PBXGroup section */ 70 | 9F0B624417358ECB00B2AAE9 = { 71 | isa = PBXGroup; 72 | children = ( 73 | 9F0B627317358ED900B2AAE9 /* DMGesturedNavigationController */, 74 | 9F0B625617358ECB00B2AAE9 /* Example */, 75 | 9F0B624F17358ECB00B2AAE9 /* Frameworks */, 76 | 9F0B624E17358ECB00B2AAE9 /* Products */, 77 | ); 78 | sourceTree = ""; 79 | }; 80 | 9F0B624E17358ECB00B2AAE9 /* Products */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 9F0B624D17358ECB00B2AAE9 /* DMGesturedNavigationController.app */, 84 | ); 85 | name = Products; 86 | sourceTree = ""; 87 | }; 88 | 9F0B624F17358ECB00B2AAE9 /* Frameworks */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 53595AC9174282A2002CBF6B /* QuartzCore.framework */, 92 | 9F0B625017358ECB00B2AAE9 /* UIKit.framework */, 93 | 9F0B625217358ECB00B2AAE9 /* Foundation.framework */, 94 | 9F0B625417358ECB00B2AAE9 /* CoreGraphics.framework */, 95 | ); 96 | name = Frameworks; 97 | sourceTree = ""; 98 | }; 99 | 9F0B625617358ECB00B2AAE9 /* Example */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 9F0B625F17358ECB00B2AAE9 /* AppDelegate.h */, 103 | 9F0B626017358ECB00B2AAE9 /* AppDelegate.m */, 104 | 9F0B626817358ECB00B2AAE9 /* ViewController.h */, 105 | 9F0B626917358ECB00B2AAE9 /* ViewController.m */, 106 | 53595ABE17392945002CBF6B /* WithinNavigationViewController.h */, 107 | 53595ABF17392945002CBF6B /* WithinNavigationViewController.m */, 108 | 9F0B626B17358ECB00B2AAE9 /* ViewController.xib */, 109 | 53595AC4173954E0002CBF6B /* ChoiceViewController.h */, 110 | 53595AC5173954E0002CBF6B /* ChoiceViewController.m */, 111 | 53595AC6173954E0002CBF6B /* ChoiceViewController.xib */, 112 | 9F0B625717358ECB00B2AAE9 /* Supporting Files */, 113 | ); 114 | name = Example; 115 | path = DMGesturedNavigationController; 116 | sourceTree = ""; 117 | }; 118 | 9F0B625717358ECB00B2AAE9 /* Supporting Files */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 9F0B625817358ECB00B2AAE9 /* DMGesturedNavigationController-Info.plist */, 122 | 9F0B625917358ECB00B2AAE9 /* InfoPlist.strings */, 123 | 9F0B625C17358ECB00B2AAE9 /* main.m */, 124 | 9F0B625E17358ECB00B2AAE9 /* DMGesturedNavigationController-Prefix.pch */, 125 | 9F0B626217358ECB00B2AAE9 /* Default.png */, 126 | 9F0B626417358ECB00B2AAE9 /* Default@2x.png */, 127 | 9F0B626617358ECB00B2AAE9 /* Default-568h@2x.png */, 128 | ); 129 | name = "Supporting Files"; 130 | sourceTree = ""; 131 | }; 132 | 9F0B627317358ED900B2AAE9 /* DMGesturedNavigationController */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 9F0B627417358EEC00B2AAE9 /* DMGesturedNavigationController.h */, 136 | 9F0B627517358EEC00B2AAE9 /* DMGesturedNavigationController.m */, 137 | ); 138 | name = DMGesturedNavigationController; 139 | sourceTree = ""; 140 | }; 141 | /* End PBXGroup section */ 142 | 143 | /* Begin PBXNativeTarget section */ 144 | 9F0B624C17358ECB00B2AAE9 /* DMGesturedNavigationController */ = { 145 | isa = PBXNativeTarget; 146 | buildConfigurationList = 9F0B627017358ECB00B2AAE9 /* Build configuration list for PBXNativeTarget "DMGesturedNavigationController" */; 147 | buildPhases = ( 148 | 9F0B624917358ECB00B2AAE9 /* Sources */, 149 | 9F0B624A17358ECB00B2AAE9 /* Frameworks */, 150 | 9F0B624B17358ECB00B2AAE9 /* Resources */, 151 | ); 152 | buildRules = ( 153 | ); 154 | dependencies = ( 155 | ); 156 | name = DMGesturedNavigationController; 157 | productName = DMGesturedNavigationController; 158 | productReference = 9F0B624D17358ECB00B2AAE9 /* DMGesturedNavigationController.app */; 159 | productType = "com.apple.product-type.application"; 160 | }; 161 | /* End PBXNativeTarget section */ 162 | 163 | /* Begin PBXProject section */ 164 | 9F0B624517358ECB00B2AAE9 /* Project object */ = { 165 | isa = PBXProject; 166 | attributes = { 167 | LastUpgradeCheck = 0460; 168 | ORGANIZATIONNAME = "Thomas Ricouard"; 169 | }; 170 | buildConfigurationList = 9F0B624817358ECB00B2AAE9 /* Build configuration list for PBXProject "DMGesturedNavigationController" */; 171 | compatibilityVersion = "Xcode 3.2"; 172 | developmentRegion = English; 173 | hasScannedForEncodings = 0; 174 | knownRegions = ( 175 | en, 176 | ); 177 | mainGroup = 9F0B624417358ECB00B2AAE9; 178 | productRefGroup = 9F0B624E17358ECB00B2AAE9 /* Products */; 179 | projectDirPath = ""; 180 | projectRoot = ""; 181 | targets = ( 182 | 9F0B624C17358ECB00B2AAE9 /* DMGesturedNavigationController */, 183 | ); 184 | }; 185 | /* End PBXProject section */ 186 | 187 | /* Begin PBXResourcesBuildPhase section */ 188 | 9F0B624B17358ECB00B2AAE9 /* Resources */ = { 189 | isa = PBXResourcesBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | 9F0B625B17358ECB00B2AAE9 /* InfoPlist.strings in Resources */, 193 | 9F0B626317358ECB00B2AAE9 /* Default.png in Resources */, 194 | 9F0B626517358ECB00B2AAE9 /* Default@2x.png in Resources */, 195 | 9F0B626717358ECB00B2AAE9 /* Default-568h@2x.png in Resources */, 196 | 9F0B626D17358ECB00B2AAE9 /* ViewController.xib in Resources */, 197 | 53595AC8173954E0002CBF6B /* ChoiceViewController.xib in Resources */, 198 | ); 199 | runOnlyForDeploymentPostprocessing = 0; 200 | }; 201 | /* End PBXResourcesBuildPhase section */ 202 | 203 | /* Begin PBXSourcesBuildPhase section */ 204 | 9F0B624917358ECB00B2AAE9 /* Sources */ = { 205 | isa = PBXSourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | 9F0B625D17358ECB00B2AAE9 /* main.m in Sources */, 209 | 9F0B626117358ECB00B2AAE9 /* AppDelegate.m in Sources */, 210 | 9F0B626A17358ECB00B2AAE9 /* ViewController.m in Sources */, 211 | 9F0B627617358EEC00B2AAE9 /* DMGesturedNavigationController.m in Sources */, 212 | 53595AC017392945002CBF6B /* WithinNavigationViewController.m in Sources */, 213 | 53595AC7173954E0002CBF6B /* ChoiceViewController.m in Sources */, 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | /* End PBXSourcesBuildPhase section */ 218 | 219 | /* Begin PBXVariantGroup section */ 220 | 9F0B625917358ECB00B2AAE9 /* InfoPlist.strings */ = { 221 | isa = PBXVariantGroup; 222 | children = ( 223 | 9F0B625A17358ECB00B2AAE9 /* en */, 224 | ); 225 | name = InfoPlist.strings; 226 | sourceTree = ""; 227 | }; 228 | 9F0B626B17358ECB00B2AAE9 /* ViewController.xib */ = { 229 | isa = PBXVariantGroup; 230 | children = ( 231 | 9F0B626C17358ECB00B2AAE9 /* en */, 232 | ); 233 | name = ViewController.xib; 234 | sourceTree = ""; 235 | }; 236 | /* End PBXVariantGroup section */ 237 | 238 | /* Begin XCBuildConfiguration section */ 239 | 9F0B626E17358ECB00B2AAE9 /* Debug */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | ALWAYS_SEARCH_USER_PATHS = NO; 243 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 244 | CLANG_CXX_LIBRARY = "libc++"; 245 | CLANG_ENABLE_OBJC_ARC = YES; 246 | CLANG_WARN_CONSTANT_CONVERSION = YES; 247 | CLANG_WARN_EMPTY_BODY = YES; 248 | CLANG_WARN_ENUM_CONVERSION = YES; 249 | CLANG_WARN_INT_CONVERSION = YES; 250 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 251 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 252 | COPY_PHASE_STRIP = NO; 253 | GCC_C_LANGUAGE_STANDARD = gnu99; 254 | GCC_DYNAMIC_NO_PIC = NO; 255 | GCC_OPTIMIZATION_LEVEL = 0; 256 | GCC_PREPROCESSOR_DEFINITIONS = ( 257 | "DEBUG=1", 258 | "$(inherited)", 259 | ); 260 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 261 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 262 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 263 | GCC_WARN_UNUSED_VARIABLE = YES; 264 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 265 | ONLY_ACTIVE_ARCH = YES; 266 | SDKROOT = iphoneos; 267 | }; 268 | name = Debug; 269 | }; 270 | 9F0B626F17358ECB00B2AAE9 /* Release */ = { 271 | isa = XCBuildConfiguration; 272 | buildSettings = { 273 | ALWAYS_SEARCH_USER_PATHS = NO; 274 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 275 | CLANG_CXX_LIBRARY = "libc++"; 276 | CLANG_ENABLE_OBJC_ARC = YES; 277 | CLANG_WARN_CONSTANT_CONVERSION = YES; 278 | CLANG_WARN_EMPTY_BODY = YES; 279 | CLANG_WARN_ENUM_CONVERSION = YES; 280 | CLANG_WARN_INT_CONVERSION = YES; 281 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 282 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 283 | COPY_PHASE_STRIP = YES; 284 | GCC_C_LANGUAGE_STANDARD = gnu99; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 286 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 287 | GCC_WARN_UNUSED_VARIABLE = YES; 288 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 289 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 290 | SDKROOT = iphoneos; 291 | VALIDATE_PRODUCT = YES; 292 | }; 293 | name = Release; 294 | }; 295 | 9F0B627117358ECB00B2AAE9 /* Debug */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 299 | GCC_PREFIX_HEADER = "DMGesturedNavigationController/DMGesturedNavigationController-Prefix.pch"; 300 | INFOPLIST_FILE = "DMGesturedNavigationController/DMGesturedNavigationController-Info.plist"; 301 | PRODUCT_NAME = "$(TARGET_NAME)"; 302 | WRAPPER_EXTENSION = app; 303 | }; 304 | name = Debug; 305 | }; 306 | 9F0B627217358ECB00B2AAE9 /* Release */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 310 | GCC_PREFIX_HEADER = "DMGesturedNavigationController/DMGesturedNavigationController-Prefix.pch"; 311 | INFOPLIST_FILE = "DMGesturedNavigationController/DMGesturedNavigationController-Info.plist"; 312 | PRODUCT_NAME = "$(TARGET_NAME)"; 313 | WRAPPER_EXTENSION = app; 314 | }; 315 | name = Release; 316 | }; 317 | /* End XCBuildConfiguration section */ 318 | 319 | /* Begin XCConfigurationList section */ 320 | 9F0B624817358ECB00B2AAE9 /* Build configuration list for PBXProject "DMGesturedNavigationController" */ = { 321 | isa = XCConfigurationList; 322 | buildConfigurations = ( 323 | 9F0B626E17358ECB00B2AAE9 /* Debug */, 324 | 9F0B626F17358ECB00B2AAE9 /* Release */, 325 | ); 326 | defaultConfigurationIsVisible = 0; 327 | defaultConfigurationName = Release; 328 | }; 329 | 9F0B627017358ECB00B2AAE9 /* Build configuration list for PBXNativeTarget "DMGesturedNavigationController" */ = { 330 | isa = XCConfigurationList; 331 | buildConfigurations = ( 332 | 9F0B627117358ECB00B2AAE9 /* Debug */, 333 | 9F0B627217358ECB00B2AAE9 /* Release */, 334 | ); 335 | defaultConfigurationIsVisible = 0; 336 | defaultConfigurationName = Release; 337 | }; 338 | /* End XCConfigurationList section */ 339 | }; 340 | rootObject = 9F0B624517358ECB00B2AAE9 /* Project object */; 341 | } 342 | -------------------------------------------------------------------------------- /Classes/DMGesturedNavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DMGesturedNavigationController.m 3 | // DMGesturedNavigationController 4 | // 5 | // Created by Thomas Ricouard on 04/05/13. 6 | // Copyright (c) 2013 Thomas Ricouard. All rights reserved. 7 | // 8 | 9 | #import "DMGesturedNavigationController.h" 10 | #import 11 | #import 12 | #import 13 | 14 | static char kVisible; 15 | static char kActive; 16 | 17 | @interface UIViewController (UIViewControllerGesturedNavigationControllerPrivate) 18 | @property (nonatomic, readwrite, getter = isVisible) BOOL visible; 19 | @property (nonatomic, readwrite, getter = isActive) BOOL active; 20 | @end 21 | 22 | @interface DMGesturedNavigationController () 23 | { 24 | NSMutableArray *_internalViewControllers; 25 | NSInteger _previousPage; 26 | UIViewController *_tmpStackedViewController; 27 | UIViewController *_tmpPreviousViewController; 28 | } 29 | 30 | @property (nonatomic, readwrite, strong) UIViewController *visibleViewController; 31 | @property (nonatomic, readwrite, strong) UIScrollView *containerScrollView; 32 | @property (nonatomic, readwrite, strong) UINavigationBar *navigationBar; 33 | @property (nonatomic) NSInteger currentPage; 34 | 35 | - (void)reloadChildViewControllersTryToRebuildStack:(BOOL)rebuildStack; 36 | - (void)rebuildNavBarStack; 37 | - (void)pageChanged; 38 | - (void)pushBack; 39 | - (void)enableScrollToTop; 40 | - (void)scrollToPage:(NSInteger)page animated:(BOOL)animated; 41 | - (void)pushExternalViewController:(UIViewController *)viewController 42 | animted:(BOOL)animated 43 | removeInBetweeenViewController:(BOOL)removeInBetweeenVC; 44 | - (UIViewController *)viewControllerForPage:(NSInteger)page; 45 | - (NSInteger)pageForViewController:(UIViewController *)viewController; 46 | - (NSInteger)currentOffset; 47 | - (CGRect)rectForViewController:(UIViewController *)viewController; 48 | - (NSArray *)viewControllers; 49 | - (void)notifyVisiblesViewController; 50 | + (CGFloat)sdkVersion; 51 | + (BOOL)isIOS7; 52 | @end 53 | 54 | @implementation DMGesturedNavigationController 55 | @dynamic viewControllers; 56 | @dynamic allowSideBoucing; 57 | @dynamic allowSwipeTransition; 58 | @dynamic backgroundColor; 59 | 60 | #pragma mark - Init stuff 61 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 62 | { 63 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 64 | if (self) { 65 | _internalViewControllers = [[NSMutableArray alloc]init]; 66 | _navigationBarHidden = NO; 67 | _animatedNavbarChange = YES; 68 | _displayEdgeShadow = YES; 69 | _minimumScaleOnSwipe = 0.8f; 70 | _scalingWhenSwipe = NO; 71 | _maximumInclinaisonAngle = 10.0f; 72 | _rotateYAxisWhenSwipe = NO; 73 | _stackType = DMGesturedNavigationControllerStackNavigationFree; 74 | _popAnimationType = DMGesturedNavigationControllerPopAnimationNewWay; 75 | } 76 | return self; 77 | } 78 | 79 | - (id)initWithRootViewController:(UIViewController *)rootViewController 80 | { 81 | self = [self initWithNibName:nil bundle:nil]; 82 | if (self) { 83 | [_internalViewControllers addObject:rootViewController]; 84 | } 85 | return self; 86 | } 87 | 88 | - (id)initWithViewControllers:(NSArray *)viewControllers 89 | { 90 | self = [self initWithNibName:nil bundle:nil]; 91 | if (self) { 92 | 93 | _internalViewControllers = [viewControllers mutableCopy]; 94 | } 95 | return self; 96 | } 97 | 98 | #pragma mark - View stuff 99 | 100 | - (void)loadView 101 | { 102 | [super loadView]; 103 | _containerScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 104 | [DMGesturedNavigationController standardNavBarHeight], 105 | self.view.frame.size.width, 106 | self.view.frame.size.height)]; 107 | [self.containerScrollView setDelegate:self]; 108 | [self.containerScrollView setPagingEnabled:YES]; 109 | [self.containerScrollView setBackgroundColor:[UIColor clearColor]]; 110 | [self.containerScrollView setShowsHorizontalScrollIndicator:NO]; 111 | [self.containerScrollView setShowsVerticalScrollIndicator:YES]; 112 | [self.containerScrollView setScrollsToTop:NO]; 113 | [self.containerScrollView setAutoresizingMask:UIViewAutoresizingFlexibleHeight| 114 | UIViewAutoresizingFlexibleWidth]; 115 | if ([DMGesturedNavigationController isIOS7]) { 116 | [self performSelector:@selector(setAutomaticallyAdjustsScrollViewInsets:) 117 | withObject:NO]; 118 | } 119 | [self.view addSubview:self.containerScrollView]; 120 | _navigationBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 121 | 0, 122 | self.view.frame.size.width, 123 | [DMGesturedNavigationController standardNavBarHeight])]; 124 | [self.navigationBar setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 125 | [self.view addSubview:self.navigationBar]; 126 | _currentPage = 0; 127 | _previousPage = 0; 128 | 129 | UIViewController *controller = [_internalViewControllers objectAtIndex:_currentPage]; 130 | [self.navigationBar pushNavigationItem:controller.navigationItem animated:self.isAnimatedNavbarChange]; 131 | controller.active = YES; 132 | controller.visible = YES; 133 | if ([controller respondsToSelector:@selector(childViewControllerdidShow)]) { 134 | [controller performSelector:@selector(childViewControllerdidShow)]; 135 | } 136 | if ([controller respondsToSelector:@selector(childViewControllerdidBecomeActive)]) { 137 | [controller performSelector:@selector(childViewControllerdidBecomeActive)]; 138 | } 139 | 140 | [self setNavigationBarHidden:NO animated:NO]; 141 | [self reloadChildViewControllersTryToRebuildStack:NO]; 142 | [self addObserver:self forKeyPath:@"navigationBarHidden" 143 | options:NSKeyValueObservingOptionNew 144 | context:nil]; 145 | [self addObserver:self forKeyPath:@"currentPage" 146 | options:NSKeyValueObservingOptionNew 147 | context:nil]; 148 | [self enableScrollToTop]; 149 | } 150 | 151 | - (void)viewDidLoad 152 | { 153 | [super viewDidLoad]; 154 | 155 | // Do any additional setup after loading the view. 156 | } 157 | 158 | - (void)viewWillDisappear:(BOOL)animated 159 | { 160 | [super viewWillDisappear:animated]; 161 | } 162 | 163 | - (void)viewWillAppear:(BOOL)animated 164 | { 165 | [super viewWillAppear:animated]; 166 | } 167 | 168 | - (void)viewDidDisappear:(BOOL)animated 169 | { 170 | [super viewDidDisappear:animated]; 171 | } 172 | 173 | - (void)viewDidAppear:(BOOL)animated 174 | { 175 | [super viewDidAppear:animated]; 176 | UIViewController *controller = [_internalViewControllers objectAtIndex:_currentPage]; 177 | if ([controller respondsToSelector:@selector(childViewControllerCouldProvideTitle)]){ 178 | [controller performSelector:@selector(childViewControllerCouldProvideTitle)]; 179 | } 180 | } 181 | 182 | - (void)dealloc 183 | { 184 | //[self removeObserver:self forKeyPath:@"navigationBarHidden"]; 185 | //[self removeObserver:self forKeyPath:@"currentPage"]; 186 | } 187 | 188 | 189 | #pragma mark - KVO 190 | 191 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 192 | { 193 | if ([keyPath isEqualToString:@"navigationBarHidden"] || [keyPath isEqualToString:@"hidden"]) { 194 | [self setNavigationBarHidden:[[self valueForKey:@"navigationBarHidden"]boolValue] animated:NO]; 195 | } 196 | else if ([keyPath isEqualToString:@"currentPage"]){ 197 | [self pageChanged]; 198 | } 199 | } 200 | 201 | 202 | #pragma mark - intenral mess 203 | - (void)reloadChildViewControllersTryToRebuildStack:(BOOL)rebuildStack 204 | { 205 | for (UIViewController *viewController in _internalViewControllers) { 206 | [viewController willMoveToParentViewController:nil]; 207 | [viewController removeFromParentViewController]; 208 | [viewController.view removeFromSuperview]; 209 | [viewController didMoveToParentViewController:nil]; 210 | } 211 | for (UIViewController *viewController in _internalViewControllers) { 212 | NSInteger index = [_internalViewControllers indexOfObject:viewController]; 213 | viewController.view.frame = CGRectMake(self.containerScrollView.frame.size.width * index, 214 | 0, 215 | self.containerScrollView.frame.size.width, 216 | self.containerScrollView.frame.size.height); 217 | [viewController willMoveToParentViewController:self]; 218 | [self addChildViewController:viewController]; 219 | [self.containerScrollView addSubview:viewController.view]; 220 | [viewController didMoveToParentViewController:self]; 221 | } 222 | 223 | self.containerScrollView.contentSize = CGSizeMake(self.containerScrollView.frame.size.width * [_internalViewControllers count], 1); 224 | if (rebuildStack) { 225 | [self rebuildNavBarStack]; 226 | } 227 | if (self.isDisplayEdgeShadow) { 228 | for (UIViewController *viewController in _internalViewControllers) { 229 | CGRect shadowFrame = viewController.view.layer.bounds; 230 | CALayer *layer = viewController.view.layer; 231 | layer.shadowOffset = CGSizeMake(0, 0); 232 | if ([_internalViewControllers indexOfObject:viewController] == 0) { 233 | layer.shadowOpacity = .5f; 234 | shadowFrame.origin.x -= 3.0; 235 | } 236 | else if ([_internalViewControllers indexOfObject:viewController] == _internalViewControllers.count - 1) { 237 | layer.shadowOpacity = .5f; 238 | shadowFrame.origin.x += 5.0; 239 | } 240 | else{ 241 | layer.shadowOpacity = 0.0f; 242 | } 243 | layer.shadowPath = [UIBezierPath bezierPathWithRect:shadowFrame].CGPath; 244 | } 245 | } 246 | else{ 247 | for (UIViewController *viewController in _internalViewControllers) { 248 | CALayer *layer = viewController.view.layer; 249 | layer.shadowOpacity = 0.0f; 250 | } 251 | } 252 | } 253 | 254 | - (void)rebuildNavBarStack 255 | { 256 | NSMutableArray *items = [[NSMutableArray alloc]init]; 257 | for (UIViewController *controller in _internalViewControllers) { 258 | [controller.navigationItem setHidesBackButton:YES]; 259 | [items addObject:controller.navigationItem]; 260 | NSUInteger index = [_internalViewControllers indexOfObject:controller]; 261 | if (index == _currentPage) { 262 | break; 263 | } 264 | } 265 | [self.navigationBar setItems:items animated:self.isAnimatedNavbarChange]; 266 | } 267 | 268 | - (void)pageChanged 269 | { 270 | UIViewController *current = [self visibleViewController]; 271 | [current viewDidAppear:YES]; 272 | UIViewController *previousInStack = current.previousViewController; 273 | _tmpPreviousViewController = [_internalViewControllers objectAtIndex:_previousPage]; 274 | if ([_tmpPreviousViewController respondsToSelector:@selector(childViewControllerCouldBecomeInactive)]) { 275 | [_tmpPreviousViewController performSelector:@selector(childViewControllerCouldBecomeInactive)]; 276 | } 277 | 278 | if ([current respondsToSelector:@selector(childViewControllerCouldBecomeActive)]) { 279 | [current performSelector:@selector(childViewControllerCouldBecomeActive)]; 280 | } 281 | NSString *title = @"Back"; 282 | if (previousInStack.title) { 283 | title = previousInStack.title; 284 | } 285 | if (self.currentPage != 0) { 286 | if ([current respondsToSelector:@selector(childViewControllerCouldProvideTitle)]){ 287 | [current performSelector:@selector(childViewControllerCouldProvideTitle)]; 288 | } 289 | UINavigationItem *newItem = current.navigationItem; 290 | if (current.navigationItem.leftBarButtonItem || current.navigationItem.leftBarButtonItems) { 291 | if (current.navigationItem.leftBarButtonItems.count > 0) { 292 | newItem.leftBarButtonItems = current.navigationItem.leftBarButtonItems; 293 | } 294 | else{ 295 | newItem.leftBarButtonItem = current.navigationItem.leftBarButtonItem; 296 | } 297 | } 298 | else{ 299 | [newItem setHidesBackButton:YES]; 300 | UIBarButtonItem *item; 301 | if (_customBackButtonItem) { 302 | _customBackButtonItem.title = previousInStack.title; 303 | item = _customBackButtonItem; 304 | } 305 | else{ 306 | item = [[UIBarButtonItem alloc]initWithTitle:title 307 | style:UIBarButtonItemStyleBordered 308 | target:self 309 | action:@selector(pushBack)]; 310 | } 311 | 312 | newItem.leftBarButtonItem = item; 313 | } 314 | if (self.currentPage < _previousPage) { 315 | [self.navigationBar popNavigationItemAnimated:self.isAnimatedNavbarChange]; 316 | _tmpStackedViewController = [self viewControllerForPage:_previousPage]; 317 | } 318 | else{ 319 | _tmpStackedViewController = nil; 320 | [self.navigationBar pushNavigationItem:newItem animated:self.isAnimatedNavbarChange]; 321 | } 322 | } 323 | else{ 324 | if ([current respondsToSelector:@selector(childViewControllerCouldProvideTitle)]){ 325 | [current performSelector:@selector(childViewControllerCouldProvideTitle)]; 326 | } 327 | [self rebuildNavBarStack]; 328 | _tmpStackedViewController = [self viewControllerForPage:_previousPage]; 329 | } 330 | _previousPage = self.currentPage; 331 | [self enableScrollToTop]; 332 | } 333 | 334 | - (void)enableScrollToTop 335 | { 336 | for (UIViewController *viewController in self.viewControllers) { 337 | NSInteger index = [self.viewControllers indexOfObject:viewController]; 338 | if (index != self.currentPage) { 339 | for (UIView *subview in [viewController.view subviews]) { 340 | if ([subview respondsToSelector:@selector(scrollsToTop)]) { 341 | [(UIScrollView *)subview setScrollsToTop:NO]; 342 | } 343 | } 344 | } 345 | else{ 346 | for (UIView *subview in [viewController.view subviews]) { 347 | if ([subview respondsToSelector:@selector(scrollsToTop)]) { 348 | [(UIScrollView *)subview setScrollsToTop:YES]; 349 | } 350 | } 351 | 352 | } 353 | } 354 | } 355 | 356 | - (void)pushBack 357 | { 358 | [self popViewControllerAnimated:YES]; 359 | } 360 | 361 | - (void)scrollToPage:(NSInteger)page animated:(BOOL)animated 362 | { 363 | [self.containerScrollView 364 | setContentOffset:CGPointMake(self.view.frame.size.width * page, 0.0f) 365 | animated:animated]; 366 | } 367 | 368 | 369 | - (UIViewController *)viewControllerForPage:(NSInteger)page 370 | { 371 | NSAssert([_internalViewControllers count] > page, 372 | @"Requested controller is out of bound"); 373 | return [_internalViewControllers objectAtIndex:page]; 374 | } 375 | 376 | 377 | - (NSInteger)pageForViewController:(UIViewController *)viewController 378 | { 379 | NSAssert([_internalViewControllers containsObject:viewController], 380 | @"Passed view controller is not a child or in the hierarchy of DMGesturesNavigationController"); 381 | return [_internalViewControllers indexOfObject:viewController]; 382 | } 383 | 384 | 385 | #pragma mark - External view controller mess 386 | - (void)pushViewController:(UIViewController *)viewController 387 | animated:(BOOL)animated 388 | removeInBetweenViewControllers:(BOOL)removeInBetweenVC 389 | { 390 | [self pushExternalViewController:viewController 391 | animted:animated 392 | removeInBetweeenViewController:removeInBetweenVC]; 393 | } 394 | 395 | - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated 396 | { 397 | [self pushExternalViewController:viewController 398 | animted:animated 399 | removeInBetweeenViewController:YES]; 400 | } 401 | 402 | - (void)pushExternalViewController:(UIViewController *)viewController 403 | animted:(BOOL)animated 404 | removeInBetweeenViewController:(BOOL)removeInBetweeenVC 405 | { 406 | if (removeInBetweeenVC) { 407 | for (NSInteger i = 0; i <= _internalViewControllers.count - 1; i++) { 408 | if (i > self.currentPage) { 409 | UIViewController *controller = [_internalViewControllers objectAtIndex:i]; 410 | [controller willMoveToParentViewController:nil]; 411 | [controller removeFromParentViewController]; 412 | [controller.view removeFromSuperview]; 413 | [_internalViewControllers removeObject:controller]; 414 | [controller didMoveToParentViewController:nil]; 415 | i--; 416 | } 417 | } 418 | } 419 | [_internalViewControllers addObject:viewController]; 420 | if (removeInBetweeenVC) { 421 | [self reloadChildViewControllersTryToRebuildStack:NO]; 422 | } 423 | else{ 424 | [self reloadChildViewControllersTryToRebuildStack:YES]; 425 | } 426 | [self scrollToPage:_internalViewControllers.count - 1 animated:animated]; 427 | } 428 | 429 | - (void)inserViewController:(UIViewController *)viewController 430 | atStackOffset:(NSInteger)offset 431 | animated:(BOOL)animated 432 | { 433 | if (offset > _internalViewControllers.count - 1) { 434 | offset = 1; 435 | } 436 | [_internalViewControllers insertObject:viewController atIndex:offset]; 437 | [self reloadChildViewControllersTryToRebuildStack:YES]; 438 | [self scrollToPage:offset animated:animated]; 439 | } 440 | 441 | - (void)removeViewController:(UIViewController *)viewControlller 442 | animated:(BOOL)animated 443 | { 444 | NSAssert([self containViewController:viewControlller], 445 | @"The passed view controller is not in the hierarchy"); 446 | NSAssert([self pageForViewController:viewControlller] > 0, 447 | @"You cannot remove the root view controller"); 448 | [viewControlller willMoveToParentViewController:nil]; 449 | if (_currentPage == [self pageForViewController:viewControlller]) { 450 | [self scrollToPage:_currentPage - 1 animated:YES]; 451 | } 452 | if (self.popAnimationType == DMGesturedNavigationControllerPopAnimationNewWay) { 453 | [UIView animateWithDuration:0.30 animations:^{ 454 | CGAffineTransform xForm = viewControlller.view.transform; 455 | viewControlller.view.transform = CGAffineTransformScale(xForm, 0.50, 0.50); 456 | }completion:^(BOOL finished) { 457 | [viewControlller.view removeFromSuperview]; 458 | [viewControlller removeFromParentViewController]; 459 | [_internalViewControllers removeObject:viewControlller]; 460 | [viewControlller didMoveToParentViewController:nil]; 461 | [self reloadChildViewControllersTryToRebuildStack:NO]; 462 | }]; 463 | } 464 | else{ 465 | [viewControlller.view removeFromSuperview]; 466 | [viewControlller removeFromParentViewController]; 467 | [_internalViewControllers removeObject:viewControlller]; 468 | [viewControlller didMoveToParentViewController:nil]; 469 | [self reloadChildViewControllersTryToRebuildStack:YES]; 470 | } 471 | 472 | } 473 | 474 | - (void)popToRootViewControllerAnimated:(BOOL)animated 475 | { 476 | [self scrollToPage:0 animated:animated]; 477 | } 478 | 479 | - (void)popViewControllerAnimated:(BOOL)animated 480 | { 481 | if (self.stackType == DMGesturedNavigationControllerStackLikeNavigationController && 482 | self.popAnimationType == DMGesturedNavigationControllerPopAnimationNewWay) { 483 | UIViewController *vcToRemove = [_internalViewControllers objectAtIndex:_currentPage]; 484 | [self removeViewController:vcToRemove animated:YES]; 485 | } 486 | else{ 487 | if (_currentPage >= 1) { 488 | [self scrollToPage:self.currentPage - 1 animated:animated]; 489 | } 490 | } 491 | } 492 | 493 | - (void)navigateToViewController:(UIViewController *)viewController animated:(BOOL)animated 494 | { 495 | NSAssert([_internalViewControllers containsObject:viewController], 496 | @"Passed view controller is not a child or in the hierarchy of DMGesturesNavigationController"); 497 | NSInteger page = [_internalViewControllers indexOfObject:viewController]; 498 | [self scrollToPage:page animated:animated]; 499 | } 500 | 501 | - (UIViewController *)visibleViewController 502 | { 503 | return [_internalViewControllers objectAtIndex:self.currentPage]; 504 | } 505 | 506 | - (UIViewController *)topViewController 507 | { 508 | return [_internalViewControllers objectAtIndex:0]; 509 | } 510 | 511 | - (BOOL)containViewController:(UIViewController *)viewController 512 | { 513 | return [_internalViewControllers containsObject:viewController]; 514 | } 515 | 516 | #pragma mark - getters & setters 517 | 518 | - (void)setBackgroundColor:(UIColor *)backgroundColor 519 | { 520 | [self.containerScrollView setBackgroundColor:backgroundColor]; 521 | } 522 | 523 | - (UIColor *)backgroundColor 524 | { 525 | return self.containerScrollView.backgroundColor; 526 | } 527 | 528 | - (void)setDisplayEdgeShadow:(BOOL)displayEdgeShadow 529 | { 530 | _displayEdgeShadow = displayEdgeShadow; 531 | [self reloadChildViewControllersTryToRebuildStack:NO]; 532 | } 533 | 534 | - (BOOL)isAllowSideBoucing 535 | { 536 | return [self.containerScrollView bounces]; 537 | } 538 | 539 | - (void)setAllowSideBoucing:(BOOL)allowSideBoucing 540 | { 541 | [self.containerScrollView setBounces:allowSideBoucing]; 542 | } 543 | 544 | - (BOOL)isAllowSwipeTransition 545 | { 546 | return [self.containerScrollView isScrollEnabled]; 547 | } 548 | 549 | - (void)setAllowSwipeTransition:(BOOL)allowSwipeTransition 550 | { 551 | [self.containerScrollView setScrollEnabled:allowSwipeTransition]; 552 | } 553 | 554 | - (NSInteger)currentOffset 555 | { 556 | CGFloat pageWidth = self.containerScrollView.frame.size.width; 557 | return floor((self.containerScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; 558 | } 559 | 560 | - (CGRect)rectForViewController:(UIViewController *)viewController 561 | { 562 | return viewController.view.frame; 563 | } 564 | 565 | 566 | - (NSArray *)viewControllers 567 | { 568 | return [NSArray arrayWithArray:_internalViewControllers]; 569 | } 570 | 571 | - (void)setViewControllers:(NSArray *)viewControllers 572 | { 573 | _internalViewControllers = [[NSArray arrayWithArray:viewControllers]mutableCopy]; 574 | _currentPage = 0; 575 | _previousPage = 0; 576 | [self reloadChildViewControllersTryToRebuildStack:YES]; 577 | } 578 | 579 | - (void)setNavigationBarHidden:(BOOL)navigationBarHidden animated:(BOOL)animated 580 | { 581 | _navigationBarHidden = navigationBarHidden; 582 | CGRect scrollFrame = self.containerScrollView.frame; 583 | if (navigationBarHidden) { 584 | scrollFrame.origin.y = 0; 585 | scrollFrame.size.height = self.view.frame.size.height; 586 | } 587 | else{ 588 | scrollFrame.origin.y = [DMGesturedNavigationController standardNavBarHeight]; 589 | scrollFrame.size.height = self.view.frame.size.height - [DMGesturedNavigationController standardNavBarHeight]; 590 | } 591 | for (UIViewController *viewController in _internalViewControllers) { 592 | CGRect vcFrame = viewController.view.frame; 593 | CGRect navFrame = self.navigationBar.frame; 594 | if (navigationBarHidden) { 595 | vcFrame.origin.y = 0; 596 | vcFrame.size.height = self.containerScrollView.frame.size.height; 597 | navFrame.origin.y = -[DMGesturedNavigationController standardNavBarHeight]; 598 | } 599 | else{ 600 | vcFrame.origin.y = 0; 601 | vcFrame.size.height = self.containerScrollView.frame.size.height; 602 | navFrame.origin.y = 0; 603 | } 604 | if (animated) { 605 | [UIView animateWithDuration:0.2 animations:^{ 606 | [self.navigationBar setFrame:navFrame]; 607 | [viewController.view setFrame:vcFrame]; 608 | }]; 609 | } 610 | else{ 611 | [self.navigationBar setFrame:navFrame]; 612 | [viewController.view setFrame:vcFrame]; 613 | [self.navigationBar setHidden:navigationBarHidden]; 614 | } 615 | } 616 | if (animated) { 617 | [UIView animateWithDuration:0.2 animations:^{ 618 | [self.containerScrollView setFrame:scrollFrame]; 619 | }]; 620 | } 621 | else{ 622 | [self.containerScrollView setFrame:scrollFrame]; 623 | } 624 | } 625 | 626 | 627 | - (void)setCustomBackButtonItem:(UIBarButtonItem *)customBackButtonItem 628 | { 629 | _customBackButtonItem = customBackButtonItem; 630 | [self.customBackButtonItem setTarget:self]; 631 | [self.customBackButtonItem setAction:@selector(pushBack)]; 632 | if (self.currentPage != 0) { 633 | UIViewController *current = [self visibleViewController]; 634 | UINavigationItem *items = current.navigationItem; 635 | items.leftBarButtonItem = self.customBackButtonItem; 636 | } 637 | } 638 | 639 | #pragma mark - ScrollView 640 | - (void)notifyVisiblesViewController 641 | { 642 | for (UIViewController *controller in _internalViewControllers) { 643 | BOOL intersect = CGRectIntersectsRect(self.containerScrollView.bounds, controller.view.frame); 644 | if (intersect) { 645 | if ([controller respondsToSelector:@selector(childViewControllerVisiblePartDidChange:)]) { 646 | CGRect visibleFrame = CGRectIntersection(self.containerScrollView.bounds, 647 | controller.view.frame); 648 | [controller performSelector:@selector(childViewControllerVisiblePartDidChange:) 649 | withObject:[NSNumber numberWithFloat:visibleFrame.size.width]]; 650 | } 651 | if (!controller.isVisible) { 652 | controller.visible = YES; 653 | if ([controller respondsToSelector:@selector(childViewControllerdidShow)]) { 654 | [controller performSelector:@selector(childViewControllerdidShow)]; 655 | } 656 | } 657 | } 658 | else{ 659 | if (controller.isVisible) { 660 | if ([controller respondsToSelector:@selector(childViewControllerdidHide)]) { 661 | [controller performSelector:@selector(childViewControllerdidHide)]; 662 | } 663 | } 664 | controller.visible = NO; 665 | } 666 | } 667 | } 668 | 669 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 670 | { 671 | [self notifyVisiblesViewController]; 672 | NSInteger newOffset = [self currentOffset]; 673 | if (newOffset != _currentPage) { 674 | self.currentPage = newOffset; 675 | } 676 | [NSObject cancelPreviousPerformRequestsWithTarget:self]; 677 | 678 | if (self.isScalingWhenSwipe || self.isRotateYAxisWhenSwipe) { 679 | CGFloat offset = scrollView.contentOffset.x; 680 | for (UIViewController *viewController in self.viewControllers) { 681 | NSUInteger index = [self.viewControllers indexOfObject:viewController]; 682 | CGFloat width = scrollView.frame.size.width; 683 | CGFloat originXForVC = index * width; 684 | CGFloat value = (offset - originXForVC)/width; 685 | CATransform3D scaleTransform = CATransform3DIdentity; 686 | CATransform3D rotateTransform = CATransform3DIdentity; 687 | 688 | if (self.isScalingWhenSwipe) { 689 | CGFloat scale = 1.f - fabs(value); 690 | if (scale > 1.f) scale = 1.f; 691 | if (scale < self.minimumScaleOnSwipe) scale = self.minimumScaleOnSwipe; 692 | scaleTransform = CATransform3DMakeScale(scale, scale, 0); 693 | } 694 | if (self.isRotateYAxisWhenSwipe) { 695 | CGFloat dX = (offset+viewController.view.frame.size.width/2) - (originXForVC+width/2); 696 | CGFloat angle = (fabs(dX) / (width/2)) * self.maximumInclinaisonAngle; 697 | CATransform3D layerTransform = CATransform3DIdentity; 698 | layerTransform.m34 = -1.0f / 300; // perspective effect 699 | rotateTransform = CATransform3DRotate(layerTransform, 700 | angle / (180.f/M_PI), 701 | 0, 702 | value, 703 | 0); 704 | } 705 | [viewController.view.layer setTransform:CATransform3DConcat(scaleTransform, rotateTransform)]; 706 | } 707 | } 708 | 709 | [self performSelector:@selector(scrollViewDidEndScrollingAnimation:) withObject:nil afterDelay:0.1]; 710 | } 711 | 712 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView 713 | { 714 | if (self.isScalingWhenSwipe || self.isRotateYAxisWhenSwipe) { 715 | for (UIViewController *viewController in self.viewControllers) { 716 | [viewController.view setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0f, 1.0f)]; 717 | } 718 | } 719 | UIViewController *current = [self visibleViewController]; 720 | if ([current respondsToSelector:@selector(childViewControllerdidBecomeActive)]) { 721 | [current performSelector:@selector(childViewControllerdidBecomeActive)]; 722 | current.active = YES; 723 | } 724 | if ([_tmpPreviousViewController respondsToSelector:@selector(childViewControllerdidResignActive)]) { 725 | [_tmpPreviousViewController performSelector:@selector(childViewControllerdidResignActive)]; 726 | _tmpPreviousViewController.active = NO; 727 | } 728 | 729 | if (_tmpStackedViewController && 730 | self.stackType == DMGesturedNavigationControllerStackLikeNavigationController) { 731 | [_tmpStackedViewController willMoveToParentViewController:nil]; 732 | [_tmpStackedViewController.view removeFromSuperview]; 733 | [_internalViewControllers removeObject:_tmpStackedViewController]; 734 | [_tmpStackedViewController didMoveToParentViewController:nil]; 735 | _tmpStackedViewController = nil; 736 | [self reloadChildViewControllersTryToRebuildStack:YES]; 737 | } 738 | 739 | [self rebuildNavBarStack]; 740 | 741 | } 742 | 743 | #pragma mark - Rotation 744 | 745 | - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 746 | { 747 | [self reloadChildViewControllersTryToRebuildStack:YES]; 748 | } 749 | 750 | 751 | #pragma mark - Memory warning 752 | - (void)didReceiveMemoryWarning 753 | { 754 | [super didReceiveMemoryWarning]; 755 | // Dispose of any resources that can be recreated. 756 | } 757 | 758 | 759 | #pragma mark - iOS Version management 760 | 761 | 762 | + (BOOL)isIOS7 763 | { 764 | return [DMGesturedNavigationController sdkVersion] > 6.9; 765 | } 766 | 767 | + (CGFloat)sdkVersion 768 | { 769 | return [[UIDevice currentDevice]systemVersion].floatValue; 770 | } 771 | 772 | + (CGFloat)standardNavBarHeight 773 | { 774 | if ([DMGesturedNavigationController isIOS7]) { 775 | return 64.0f; 776 | } 777 | return 44.0f; 778 | } 779 | 780 | @end 781 | 782 | #pragma mark - Categories implementations 783 | @implementation UIViewController (UIViewControllerGesturedNavigationControllerPrivate) 784 | @dynamic visible; 785 | @dynamic active; 786 | 787 | - (void)setVisible:(BOOL)visible 788 | { 789 | objc_setAssociatedObject(self, 790 | &kVisible, 791 | [NSNumber numberWithBool:visible], 792 | OBJC_ASSOCIATION_RETAIN); 793 | } 794 | 795 | - (void)setActive:(BOOL)active 796 | { 797 | objc_setAssociatedObject(self, 798 | &kVisible, 799 | [NSNumber numberWithBool:active], 800 | OBJC_ASSOCIATION_RETAIN); 801 | } 802 | 803 | @end 804 | 805 | @implementation UIViewController (UIViewControllerGesturedNavigationController) 806 | @dynamic previousViewController; 807 | @dynamic nextViewController; 808 | @dynamic gesturedNavigationController; 809 | @dynamic visible; 810 | @dynamic active; 811 | @dynamic gesturedNavigationControllerOffset; 812 | 813 | - (BOOL)isVisible 814 | { 815 | NSNumber *result = objc_getAssociatedObject(self, &kVisible); 816 | return result.boolValue; 817 | } 818 | 819 | - (BOOL)isActive 820 | { 821 | NSNumber *result = objc_getAssociatedObject(self, &kActive); 822 | return result.boolValue; 823 | } 824 | 825 | 826 | - (DMGesturedNavigationController *)gesturedNavigationController 827 | { 828 | 829 | if([self.parentViewController isKindOfClass:[DMGesturedNavigationController class]]){ 830 | return (DMGesturedNavigationController*)self.parentViewController; 831 | } 832 | else if([self.parentViewController isKindOfClass:[UINavigationController class]] && 833 | [self.parentViewController.parentViewController isKindOfClass:[DMGesturedNavigationController class]]){ 834 | return (DMGesturedNavigationController*)[self.parentViewController parentViewController]; 835 | } 836 | else{ 837 | return nil; 838 | } 839 | 840 | } 841 | 842 | - (UIViewController *)previousViewController 843 | { 844 | DMGesturedNavigationController *parent = self.gesturedNavigationController; 845 | NSInteger currentPage = [parent pageForViewController:self]; 846 | if (currentPage != 0 && parent.viewControllers.count > 1) { 847 | return [parent viewControllerForPage:currentPage - 1]; 848 | } 849 | return nil; 850 | } 851 | 852 | - (UIViewController *)nextViewController 853 | { 854 | DMGesturedNavigationController *parent = self.gesturedNavigationController; 855 | NSInteger currentPage = [parent pageForViewController:self]; 856 | if (parent.viewControllers.count > currentPage + 1) { 857 | return [parent viewControllerForPage:currentPage + 1]; 858 | } 859 | return nil; 860 | } 861 | 862 | - (NSInteger)gesturedNavigationControllerOffset 863 | { 864 | if ([self.gesturedNavigationController containViewController:self]) { 865 | return [self.gesturedNavigationController pageForViewController:self]; 866 | } 867 | return 0; 868 | 869 | } 870 | 871 | - (void)pushViewControllerToSelf 872 | { 873 | [self.gesturedNavigationController navigateToViewController:self animated:YES]; 874 | } 875 | 876 | @end 877 | -------------------------------------------------------------------------------- /DMGesturedNavigationController/en.lproj/ViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 12D78 6 | 3084 7 | 1187.37 8 | 626.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBNSLayoutConstraint 15 | IBProxyObject 16 | IBUIButton 17 | IBUILabel 18 | IBUIView 19 | 20 | 21 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 22 | 23 | 24 | PluginDependencyRecalculationVersion 25 | 26 | 27 | 28 | 29 | IBFilesOwner 30 | IBCocoaTouchFramework 31 | 32 | 33 | IBFirstResponder 34 | IBCocoaTouchFramework 35 | 36 | 37 | 38 | 274 39 | 40 | 41 | 42 | 292 43 | {{24, 432}, {273, 44}} 44 | 45 | 46 | _NS:9 47 | NO 48 | IBCocoaTouchFramework 49 | 0 50 | 0 51 | 1 52 | Transition to normal nav controller 53 | 54 | 3 55 | MQA 56 | 57 | 58 | 1 59 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 60 | 61 | 62 | 3 63 | MC41AA 64 | 65 | 66 | 2 67 | 15 68 | 69 | 70 | Helvetica-Bold 71 | 15 72 | 16 73 | 74 | 75 | 76 | 77 | 292 78 | {{24, 87}, {273, 44}} 79 | 80 | 81 | 82 | _NS:9 83 | NO 84 | IBCocoaTouchFramework 85 | 0 86 | 0 87 | 1 88 | Push new view controller 89 | 90 | 91 | 1 92 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 292 101 | {{271, 1}, {29, 31}} 102 | 103 | 104 | _NS:9 105 | NO 106 | IBCocoaTouchFramework 107 | 0 108 | 0 109 | 2 110 | 111 | 112 | 1 113 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 292 122 | {{24, 217}, {273, 44}} 123 | 124 | 125 | 126 | _NS:9 127 | NO 128 | IBCocoaTouchFramework 129 | 0 130 | 0 131 | 1 132 | Push VC and preserve stack 133 | 134 | 135 | 1 136 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 292 145 | {{24, 311}, {273, 44}} 146 | 147 | 148 | 149 | _NS:9 150 | NO 151 | IBCocoaTouchFramework 152 | 0 153 | 0 154 | 1 155 | Insert VC at Offset 2 156 | 157 | 158 | 1 159 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 292 168 | {{0, 11}, {320, 73}} 169 | 170 | 171 | 172 | _NS:9 173 | NO 174 | YES 175 | 7 176 | NO 177 | IBCocoaTouchFramework 178 | Classic: Push to next and erase stack after the pushed VC 179 | 180 | 1 181 | MCAwIDAAA 182 | darkTextColor 183 | 184 | 185 | 0 186 | 3 187 | 1 188 | 189 | 1 190 | 16 191 | 192 | 193 | Helvetica 194 | 16 195 | 16 196 | 197 | NO 198 | 320 199 | 200 | 201 | 202 | 292 203 | {{0, 165}, {320, 44}} 204 | 205 | 206 | 207 | _NS:9 208 | NO 209 | YES 210 | 7 211 | NO 212 | IBCocoaTouchFramework 213 | New: Insert VC to last and navigate to it. Preserve stack in betweeen 214 | 215 | 216 | 0 217 | 3 218 | 1 219 | 220 | 1 221 | 17 222 | 223 | 224 | Helvetica 225 | 17 226 | 16 227 | 228 | NO 229 | 320 230 | 231 | 232 | 233 | 292 234 | {{10, 269}, {300, 21}} 235 | 236 | 237 | 238 | _NS:9 239 | NO 240 | YES 241 | 7 242 | NO 243 | IBCocoaTouchFramework 244 | New: Insert to offset 2 and navigate to it 245 | 246 | 247 | 0 248 | 1 249 | 250 | 251 | NO 252 | 253 | 254 | 255 | 292 256 | {{37, 129}, {234, 21}} 257 | 258 | 259 | 260 | _NS:9 261 | NO 262 | YES 263 | 7 264 | NO 265 | IBCocoaTouchFramework 266 | Like a classic UINavigationController 267 | 268 | 2 269 | MC4zNjQ3MDU4OTA0IDAuMzY4NjI3NDU4OCAwLjM4ODIzNTMzMDYAA 270 | 271 | 272 | 0 273 | 1 274 | 275 | 1 276 | 13 277 | 278 | 279 | Helvetica 280 | 13 281 | 16 282 | 283 | NO 284 | 285 | 286 | 287 | 292 288 | {{24, 370}, {276, 44}} 289 | 290 | 291 | 292 | _NS:9 293 | NO 294 | IBCocoaTouchFramework 295 | 0 296 | 0 297 | 1 298 | Remove current view controller 299 | 300 | 301 | 1 302 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 303 | 304 | 305 | 306 | 307 | 308 | 309 | {{0, 64}, {320, 504}} 310 | 311 | 312 | 313 | 314 | 3 315 | MC43NQA 316 | 317 | 2 318 | 319 | 320 | NO 321 | 322 | 323 | NO 324 | 325 | 326 | IBUIScreenMetrics 327 | 328 | YES 329 | 330 | 331 | 332 | 333 | 334 | {320, 568} 335 | {568, 320} 336 | 337 | 338 | IBCocoaTouchFramework 339 | Retina 4 Full Screen 340 | 2 341 | 342 | IBCocoaTouchFramework 343 | 344 | 345 | 346 | 347 | 348 | 349 | view 350 | 351 | 352 | 353 | 7 354 | 355 | 356 | 357 | pushNewVC 358 | 359 | 360 | 361 | 33 362 | 363 | 364 | 365 | pushVC: 366 | 367 | 368 | 7 369 | 370 | 14 371 | 372 | 373 | 374 | onPushNewVC: 375 | 376 | 377 | 7 378 | 379 | 34 380 | 381 | 382 | 383 | onPushNew: 384 | 385 | 386 | 7 387 | 388 | 89 389 | 390 | 391 | 392 | onInsert: 393 | 394 | 395 | 7 396 | 397 | 91 398 | 399 | 400 | 401 | onRemove: 402 | 403 | 404 | 7 405 | 406 | 165 407 | 408 | 409 | 410 | onHideNavBar: 411 | 412 | 413 | 7 414 | 415 | 208 416 | 417 | 418 | 419 | 420 | 421 | 0 422 | 423 | 424 | 425 | 426 | 427 | -1 428 | 429 | 430 | File's Owner 431 | 432 | 433 | -2 434 | 435 | 436 | 437 | 438 | 6 439 | 440 | 441 | 442 | 443 | 4 444 | 0 445 | 446 | 4 447 | 1 448 | 449 | 29 450 | 451 | 1000 452 | 453 | 3 454 | 9 455 | 3 456 | 457 | 458 | 459 | 5 460 | 0 461 | 462 | 5 463 | 1 464 | 465 | 0.0 466 | 467 | 1000 468 | 469 | 6 470 | 24 471 | 2 472 | 473 | 474 | 475 | 6 476 | 0 477 | 478 | 6 479 | 1 480 | 481 | 0.0 482 | 483 | 1000 484 | 485 | 6 486 | 24 487 | 2 488 | 489 | 490 | 491 | 4 492 | 0 493 | 494 | 4 495 | 1 496 | 497 | 91 498 | 499 | 1000 500 | 501 | 3 502 | 9 503 | 3 504 | 505 | 506 | 507 | 6 508 | 0 509 | 510 | 6 511 | 1 512 | 513 | 20 514 | 515 | 1000 516 | 517 | 8 518 | 29 519 | 3 520 | 521 | 522 | 523 | 5 524 | 0 525 | 526 | 5 527 | 1 528 | 529 | 0.0 530 | 531 | 1000 532 | 533 | 6 534 | 24 535 | 2 536 | 537 | 538 | 539 | 4 540 | 0 541 | 542 | 4 543 | 1 544 | 545 | 150 546 | 547 | 1000 548 | 549 | 3 550 | 9 551 | 3 552 | 553 | 554 | 555 | 6 556 | 0 557 | 558 | 6 559 | 1 560 | 561 | 0.0 562 | 563 | 1000 564 | 565 | 6 566 | 24 567 | 2 568 | 569 | 570 | 571 | 5 572 | 0 573 | 574 | 5 575 | 1 576 | 577 | 0.0 578 | 579 | 1000 580 | 581 | 6 582 | 24 583 | 2 584 | 585 | 586 | 587 | 6 588 | 0 589 | 590 | 6 591 | 1 592 | 593 | 0.0 594 | 595 | 1000 596 | 597 | 6 598 | 24 599 | 2 600 | 601 | 602 | 603 | 3 604 | 0 605 | 606 | 3 607 | 1 608 | 609 | 5 610 | 611 | 1000 612 | 613 | 3 614 | 9 615 | 3 616 | 617 | 618 | 619 | 4 620 | 0 621 | 622 | 4 623 | 1 624 | 625 | 214 626 | 627 | 1000 628 | 629 | 3 630 | 9 631 | 3 632 | 633 | 634 | 635 | 9 636 | 0 637 | 638 | 9 639 | 1 640 | 641 | 0.0 642 | 643 | 1000 644 | 645 | 6 646 | 24 647 | 2 648 | 649 | 650 | 651 | 3 652 | 0 653 | 654 | 4 655 | 1 656 | 657 | 8 658 | 659 | 1000 660 | 661 | 6 662 | 24 663 | 3 664 | 665 | 666 | 667 | 5 668 | 0 669 | 670 | 5 671 | 1 672 | 673 | 0.0 674 | 675 | 1000 676 | 677 | 6 678 | 24 679 | 2 680 | 681 | 682 | 683 | 6 684 | 0 685 | 686 | 6 687 | 1 688 | 689 | 0.0 690 | 691 | 1000 692 | 693 | 6 694 | 24 695 | 2 696 | 697 | 698 | 699 | 3 700 | 0 701 | 702 | 3 703 | 1 704 | 705 | 165 706 | 707 | 1000 708 | 709 | 3 710 | 9 711 | 3 712 | 713 | 714 | 715 | 9 716 | 0 717 | 718 | 9 719 | 1 720 | 721 | 0.0 722 | 723 | 1000 724 | 725 | 6 726 | 24 727 | 2 728 | 729 | 730 | 731 | 6 732 | 0 733 | 734 | 6 735 | 1 736 | 737 | 0.0 738 | 739 | 1000 740 | 741 | 8 742 | 29 743 | 3 744 | 745 | 746 | 747 | 5 748 | 0 749 | 750 | 5 751 | 1 752 | 753 | 0.0 754 | 755 | 1000 756 | 757 | 8 758 | 29 759 | 3 760 | 761 | 762 | 763 | 5 764 | 0 765 | 766 | 5 767 | 1 768 | 769 | 37 770 | 771 | 1000 772 | 773 | 3 774 | 9 775 | 3 776 | 777 | 778 | 779 | 3 780 | 0 781 | 782 | 3 783 | 1 784 | 785 | 129 786 | 787 | 1000 788 | 789 | 3 790 | 9 791 | 3 792 | 793 | 794 | 795 | 3 796 | 0 797 | 798 | 3 799 | 1 800 | 801 | 87 802 | 803 | 1000 804 | 805 | 3 806 | 9 807 | 3 808 | 809 | 810 | 811 | 3 812 | 0 813 | 814 | 3 815 | 1 816 | 817 | 11 818 | 819 | 1000 820 | 821 | 3 822 | 9 823 | 3 824 | 825 | 826 | 827 | 6 828 | 0 829 | 830 | 6 831 | 1 832 | 833 | 0.0 834 | 835 | 1000 836 | 837 | 8 838 | 29 839 | 3 840 | 841 | 842 | 843 | 5 844 | 0 845 | 846 | 5 847 | 1 848 | 849 | 0.0 850 | 851 | 1000 852 | 853 | 8 854 | 29 855 | 3 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 11 872 | 873 | 874 | 875 | 876 | 15 877 | 878 | 879 | 880 | 881 | 882 | 39 883 | 884 | 885 | 886 | 887 | 888 | 43 889 | 890 | 891 | 892 | 893 | 45 894 | 895 | 896 | 897 | 898 | 47 899 | 900 | 901 | 902 | 903 | 904 | 52 905 | 906 | 907 | 908 | 909 | 54 910 | 911 | 912 | 913 | 914 | 57 915 | 916 | 917 | 918 | 919 | 8 920 | 0 921 | 922 | 0 923 | 1 924 | 925 | 73 926 | 927 | 1000 928 | 929 | 3 930 | 9 931 | 1 932 | 933 | 934 | 935 | 936 | 937 | 69 938 | 939 | 940 | 941 | 942 | 8 943 | 0 944 | 945 | 0 946 | 1 947 | 948 | 44 949 | 950 | 1000 951 | 952 | 3 953 | 9 954 | 1 955 | 956 | 957 | 958 | 959 | 960 | 76 961 | 962 | 963 | 964 | 965 | 92 966 | 967 | 968 | 969 | 970 | 122 971 | 972 | 973 | 974 | 975 | 124 976 | 977 | 978 | 979 | 980 | 126 981 | 982 | 983 | 984 | 985 | 127 986 | 987 | 988 | 989 | 990 | 128 991 | 992 | 993 | 994 | 995 | 142 996 | 997 | 998 | 999 | 1000 | 143 1001 | 1002 | 1003 | 1004 | 1005 | 8 1006 | 0 1007 | 1008 | 0 1009 | 1 1010 | 1011 | 21 1012 | 1013 | 1000 1014 | 1015 | 3 1016 | 9 1017 | 1 1018 | 1019 | 1020 | 1021 | 7 1022 | 0 1023 | 1024 | 0 1025 | 1 1026 | 1027 | 234 1028 | 1029 | 1000 1030 | 1031 | 3 1032 | 9 1033 | 1 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 144 1040 | 1041 | 1042 | 1043 | 1044 | 147 1045 | 1046 | 1047 | 1048 | 1049 | 148 1050 | 1051 | 1052 | 1053 | 1054 | 150 1055 | 1056 | 1057 | 1058 | 1059 | 161 1060 | 1061 | 1062 | 1063 | 1064 | 162 1065 | 1066 | 1067 | 1068 | 1069 | 164 1070 | 1071 | 1072 | 1073 | 1074 | 174 1075 | 1076 | 1077 | 1078 | 1079 | 175 1080 | 1081 | 1082 | 1083 | 1084 | 176 1085 | 1086 | 1087 | 1088 | 1089 | 177 1090 | 1091 | 1092 | 1093 | 1094 | 178 1095 | 1096 | 1097 | 1098 | 1099 | 179 1100 | 1101 | 1102 | 1103 | 1104 | 183 1105 | 1106 | 1107 | 1108 | 1109 | 184 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 192 1116 | 1117 | 1118 | 1119 | 1120 | 120 1121 | 1122 | 1123 | 1124 | 1125 | 118 1126 | 1127 | 1128 | 1129 | 1130 | 200 1131 | 1132 | 1133 | 1134 | 1135 | 203 1136 | 1137 | 1138 | 1139 | 1140 | 206 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | ViewController 1148 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1149 | UIResponder 1150 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1151 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1152 | 1153 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1154 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1155 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1156 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1157 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1158 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1159 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1160 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1161 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1168 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1169 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1170 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1171 | 1172 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1173 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1174 | 1175 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1176 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1177 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1178 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1179 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1180 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1181 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1182 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1183 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1184 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1185 | 1186 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1187 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1188 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1189 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1190 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1191 | 1192 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1193 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1194 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1195 | 1196 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1197 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1198 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1199 | 1200 | 1201 | 1202 | 1203 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1233 | 1234 | 1235 | 1236 | 1237 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1238 | 1239 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 208 1246 | 1247 | 1248 | 1249 | 1250 | NSLayoutConstraint 1251 | NSObject 1252 | 1253 | IBProjectSource 1254 | ./Classes/NSLayoutConstraint.h 1255 | 1256 | 1257 | 1258 | ViewController 1259 | UIViewController 1260 | 1261 | id 1262 | id 1263 | id 1264 | id 1265 | id 1266 | id 1267 | 1268 | 1269 | 1270 | onHideNavBar: 1271 | id 1272 | 1273 | 1274 | onInsert: 1275 | id 1276 | 1277 | 1278 | onPushNew: 1279 | id 1280 | 1281 | 1282 | onPushNewVC: 1283 | id 1284 | 1285 | 1286 | onRemove: 1287 | id 1288 | 1289 | 1290 | pushVC: 1291 | id 1292 | 1293 | 1294 | 1295 | pushNewVC 1296 | UIButton 1297 | 1298 | 1299 | pushNewVC 1300 | 1301 | pushNewVC 1302 | UIButton 1303 | 1304 | 1305 | 1306 | IBProjectSource 1307 | ./Classes/ViewController.h 1308 | 1309 | 1310 | 1311 | 1312 | 0 1313 | IBCocoaTouchFramework 1314 | YES 1315 | 3 1316 | YES 1317 | 2083 1318 | 1319 | 1320 | --------------------------------------------------------------------------------