├── DemoAssets
├── SWScreenshot1.png
├── SWScreenRecord.gif
└── SWScreenRecord2.gif
├── SWNavigationController.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcuserdata
│ └── cewende.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── SWNavigationController.xcscheme
└── project.pbxproj
├── SWNavigationController
├── LastViewController.h
├── TableViewController.h
├── AppDelegate.h
├── PodFiles
│ ├── SWPushAnimatedTransitioning.h
│ ├── SWNavigationController.h
│ ├── SWPushAnimatedTransitioning.m
│ └── SWNavigationController.m
├── main.m
├── LastViewController.m
├── TableViewController.m
├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── AppDelegate.m
└── Base.lproj
│ ├── LaunchScreen.xib
│ └── Main.storyboard
├── SWNavigationController.podspec
├── SWNavigationControllerTests
├── Info.plist
└── SWNavigationControllerTests.m
├── LICENCE
└── README.md
/DemoAssets/SWScreenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CEWendel/SWNavigationController/HEAD/DemoAssets/SWScreenshot1.png
--------------------------------------------------------------------------------
/DemoAssets/SWScreenRecord.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CEWendel/SWNavigationController/HEAD/DemoAssets/SWScreenRecord.gif
--------------------------------------------------------------------------------
/DemoAssets/SWScreenRecord2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CEWendel/SWNavigationController/HEAD/DemoAssets/SWScreenRecord2.gif
--------------------------------------------------------------------------------
/SWNavigationController.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SWNavigationController/LastViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // LastViewController.h
3 | // SWNavigationController
4 | //
5 | // Created by Christopher Wendel on 1/1/15.
6 | // Copyright (c) 2015 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface LastViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SWNavigationController/TableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // SWNavigationController
4 | //
5 | // Created by Christopher Wendel on 12/31/14.
6 | // Copyright (c) 2014 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TableViewController : UITableViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/SWNavigationController/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // SWNavigationController
4 | //
5 | // Created by Christopher Wendel on 12/31/14.
6 | // Copyright (c) 2014 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/SWNavigationController/PodFiles/SWPushAnimatedTransitioning.h:
--------------------------------------------------------------------------------
1 | //
2 | // SWPushAnimatedTransitioning.h
3 | // SWNavigationController
4 | //
5 | // Created by Christopher Wendel on 12/31/14.
6 | // Copyright (c) 2014 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface SWPushAnimatedTransitioning : NSObject
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/SWNavigationController/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // SWNavigationController
4 | //
5 | // Created by Christopher Wendel on 12/31/14.
6 | // Copyright (c) 2014 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/SWNavigationController.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'SWNavigationController'
3 | s.version = '0.0.1'
4 | s.author = { 'Chris Wendel' => 'chriwend@umich.edu' }
5 | s.homepage = 'https://github.com/CEWendel/SWNavigationController'
6 | s.summary = 'A UINavigationController subclass and corresponding UINavigationControllerDelegate that provides drop-in support for edge-swiping left and right through a view hierarchy.'
7 | s.license = 'MIT'
8 | s.source = { :git => 'https://github.com/CEWendel/SWNavigationController.git', :tag => s.version.to_s }
9 | s.source_files = 'SWNavigationController/PodFiles/*.{h,m}'
10 | s.platform = :ios
11 | s.ios.deployment_target = '7.0'
12 | s.requires_arc = true
13 | end
14 |
--------------------------------------------------------------------------------
/SWNavigationController.xcodeproj/xcuserdata/cewende.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SWNavigationController.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 0F6F146D1A548CD400B216EF
16 |
17 | primary
18 |
19 |
20 | 0F6F14861A548CD400B216EF
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SWNavigationControllerTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.CEWendel.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Christopher Wendel
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/SWNavigationControllerTests/SWNavigationControllerTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // SWNavigationControllerTests.m
3 | // SWNavigationControllerTests
4 | //
5 | // Created by Christopher Wendel on 12/31/14.
6 | // Copyright (c) 2014 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface SWNavigationControllerTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation SWNavigationControllerTests
17 |
18 | - (void)setUp {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown {
24 | // Put teardown code here. This method is called after the invocation of each test method in the class.
25 | [super tearDown];
26 | }
27 |
28 | - (void)testExample {
29 | // This is an example of a functional test case.
30 | XCTAssert(YES, @"Pass");
31 | }
32 |
33 | - (void)testPerformanceExample {
34 | // This is an example of a performance test case.
35 | [self measureBlock:^{
36 | // Put the code you want to measure the time of here.
37 | }];
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/SWNavigationController/LastViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // LastViewController.m
3 | // SWNavigationController
4 | //
5 | // Created by Christopher Wendel on 1/1/15.
6 | // Copyright (c) 2015 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import "LastViewController.h"
10 |
11 | @interface LastViewController ()
12 |
13 | @end
14 |
15 | @implementation LastViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 | // Do any additional setup after loading the view.
20 | }
21 |
22 | - (void)didReceiveMemoryWarning {
23 | [super didReceiveMemoryWarning];
24 | // Dispose of any resources that can be recreated.
25 | }
26 |
27 | #pragma mark - IBActions
28 |
29 | - (IBAction)popPressed:(id)sender
30 | {
31 | [self.navigationController popToRootViewControllerAnimated:YES];
32 | }
33 |
34 | /*
35 | #pragma mark - Navigation
36 |
37 | // In a storyboard-based application, you will often want to do a little preparation before navigation
38 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
39 | // Get the new view controller using [segue destinationViewController].
40 | // Pass the selected object to the new view controller.
41 | }
42 | */
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/SWNavigationController/TableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // SWNavigationController
4 | //
5 | // Created by Christopher Wendel on 12/31/14.
6 | // Copyright (c) 2014 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import "TableViewController.h"
10 |
11 | @interface TableViewController ()
12 |
13 | @end
14 |
15 | @implementation TableViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 | // Do any additional setup after loading the view, typically from a nib.
20 | }
21 |
22 | - (void)didReceiveMemoryWarning {
23 | [super didReceiveMemoryWarning];
24 | // Dispose of any resources that can be recreated.
25 | }
26 |
27 | #pragma mark - UITableViewDataSource
28 |
29 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
30 | {
31 | return 100;
32 | }
33 |
34 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
35 | {
36 | static NSString *CellIdentifier = @"CellIdentifier";
37 |
38 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
39 |
40 | cell.textLabel.text = [NSString stringWithFormat:@"Cell %ld", indexPath.row];
41 |
42 | return cell;
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/SWNavigationController/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/SWNavigationController/PodFiles/SWNavigationController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SWNavigationController.h
3 | // SWNavigationController
4 | //
5 | // Created by Christopher Wendel on 12/31/14.
6 | // Copyright (c) 2014 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SWNavigationController : UINavigationController
12 |
13 | /** A gesture recognizer responsible for pushing the most recently popped view controller back onto the navigation stack. (read-only)
14 | *
15 | * Handles the right-to-left edge swipe gesture. Disable this gesture recognizer to disable the interactive push of the next view controller.
16 | * Enabled by default
17 | */
18 | @property (nonatomic, strong, readonly) UIGestureRecognizer *interactivePushGestureRecognizer;
19 |
20 | /** The Class that handles the push transition when a view controller is pushed onto the navigation stack.
21 | *
22 | * A new instance of this Class is initialized when a push occurs.
23 | * The Class must implement the protocol UIViewControllerAnimatedTransitioning.
24 | * By default this is set to SWPushAnimatedTransitioning.
25 | */
26 | @property (nonatomic, strong) Class pushAnimatedTransitioningClass;
27 |
28 |
29 | /** The Class that handles the pop transition when a view controller is popped off the navigation stack.
30 | *
31 | * A new instance of this Class is initialized when a pop occurs.
32 | * The Class must implement the protocol UIViewControllerAnimatedTransitioning
33 | * If this is nil, UINavigationController's default pop animation will be used.
34 | */
35 | @property (nonatomic, strong) Class popAnimatedTransitioningClass;
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/SWNavigationController/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.CEWendel.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/SWNavigationController/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // SWNavigationController
4 | //
5 | // Created by Christopher Wendel on 12/31/14.
6 | // Copyright (c) 2014 Christopher Wendel. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 | - (void)applicationWillResignActive:(UIApplication *)application {
24 | // 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.
25 | // 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.
26 | }
27 |
28 | - (void)applicationDidEnterBackground:(UIApplication *)application {
29 | // 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.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application {
34 | // 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.
35 | }
36 |
37 | - (void)applicationDidBecomeActive:(UIApplication *)application {
38 | // 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.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SWNavigationController
2 | ======================
3 |
4 |
5 |
6 | A UINavigationController subclass and corresponding UINavigationControllerDelegate that implements drop-in support for swiping left and right through a view hierarchy.
7 |
8 | ##Installation
9 | In your Podfile:
10 |
pod 'SWNavigationController'
11 |
12 | Or just close this repo and manually add the files from the `PodFiles` directory to your project
13 |
14 | ##Usage
15 |
16 | To use `SWNavigationController`, simply change the type of the `UINavigationController`
17 |
18 | * Either in your Storyboard
19 |
20 |
21 |
22 | * Or programmatically in your `AppDelegate`
23 | ```objc
24 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
25 | SWNavigationController *navController = [[SWNavigationController alloc] initWithRootViewController:rootViewController];
26 |
27 | [self.window setRootViewController:navController];
28 |
29 | return YES;
30 | }
31 | ```
32 |
33 | ##Functionality
34 |
35 | ### API
36 | #### Interactive Push Gesture
37 |
38 | ```objc
39 | @property (nonatomic, strong, readonly) UIGestureRecognizer *interactivePushGestureRecognizer;
40 | ```
41 | `SWNavigationController` contains a interactive push gesture recognizer, which behaves opposite of `UINavigationController`'s existing interactive pop gesture recognizer. When a view controller has been popped off the navigation stack it can be pulled back onto the top of the navigation stack by a right edge swipe.
42 |
43 | The interactive push by default attempts to behave similarly to the built-in interactive pop.
44 |
45 |