├── .gitattributes ├── .gitignore ├── Default-568h@2x.png ├── Demo ├── GHAppDelegate.h ├── GHAppDelegate.m ├── GHMenuCell.h ├── GHMenuCell.m ├── GHMenuViewController.h ├── GHMenuViewController.m ├── GHPushedViewController.h ├── GHPushedViewController.m ├── GHRootViewController.h ├── GHRootViewController.m ├── GHSidebarNav-Info.plist ├── GHSidebarNav-Prefix.pch ├── en.lproj │ └── InfoPlist.strings └── main.m ├── GHSidebarNav.podspec ├── GHSidebarNav.xcodeproj └── project.pbxproj ├── GHSidebarNav ├── GHRevealViewController.h ├── GHRevealViewController.m ├── GHSidebarSearchViewController.h ├── GHSidebarSearchViewController.m ├── GHSidebarSearchViewControllerDelegate.h └── Images │ ├── searchBarBG.png │ ├── searchBarIcon.png │ ├── searchBarIcon@2x.png │ ├── searchTextBG.png │ └── user.png ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -crlf -diff -merge 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | -------------------------------------------------------------------------------- /Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gresrun/GHSidebarNav/7133823c74238d6b65c412997ec912b2d1716fea/Default-568h@2x.png -------------------------------------------------------------------------------- /Demo/GHAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHAppDelegate.h 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | 9 | @interface GHAppDelegate : UIResponder 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Demo/GHAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHAppDelegate.m 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | #import "GHAppDelegate.h" 9 | #import "GHMenuCell.h" 10 | #import "GHMenuViewController.h" 11 | #import "GHRootViewController.h" 12 | #import "GHRevealViewController.h" 13 | #import "GHSidebarSearchViewController.h" 14 | #import "GHSidebarSearchViewControllerDelegate.h" 15 | 16 | 17 | #pragma mark Private Interface 18 | @interface GHAppDelegate () 19 | @property (nonatomic, strong) GHRevealViewController *revealController; 20 | @property (nonatomic, strong) GHSidebarSearchViewController *searchController; 21 | @property (nonatomic, strong) GHMenuViewController *menuController; 22 | @end 23 | 24 | #pragma mark Implementation 25 | @implementation GHAppDelegate 26 | 27 | #pragma mark Properties 28 | @synthesize window = _window; 29 | 30 | #pragma mark UIApplicationDelegate 31 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 32 | [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:NO]; 33 | 34 | UIColor *bgColor = [UIColor colorWithRed:(50.0f/255.0f) green:(57.0f/255.0f) blue:(74.0f/255.0f) alpha:1.0f]; 35 | self.revealController = [[GHRevealViewController alloc] initWithNibName:nil bundle:nil]; 36 | self.revealController.view.backgroundColor = bgColor; 37 | 38 | RevealBlock revealBlock = ^(){ 39 | [self.revealController toggleSidebar:!self.revealController.sidebarShowing 40 | duration:kGHRevealSidebarDefaultAnimationDuration]; 41 | }; 42 | 43 | NSArray *headers = @[ 44 | [NSNull null], 45 | @"FAVORITES" 46 | ]; 47 | NSArray *controllers = @[ 48 | @[ 49 | [[UINavigationController alloc] initWithRootViewController:[[GHRootViewController alloc] initWithTitle:@"Profile" withRevealBlock:revealBlock]] 50 | ], 51 | @[ 52 | [[UINavigationController alloc] initWithRootViewController:[[GHRootViewController alloc] initWithTitle:@"News Feed" withRevealBlock:revealBlock]], 53 | [[UINavigationController alloc] initWithRootViewController:[[GHRootViewController alloc] initWithTitle:@"Messages" withRevealBlock:revealBlock]], 54 | [[UINavigationController alloc] initWithRootViewController:[[GHRootViewController alloc] initWithTitle:@"Nearby" withRevealBlock:revealBlock]], 55 | [[UINavigationController alloc] initWithRootViewController:[[GHRootViewController alloc] initWithTitle:@"Events" withRevealBlock:revealBlock]], 56 | [[UINavigationController alloc] initWithRootViewController:[[GHRootViewController alloc] initWithTitle:@"Friends" withRevealBlock:revealBlock]] 57 | ] 58 | ]; 59 | NSArray *cellInfos = @[ 60 | @[ 61 | @{kSidebarCellImageKey: [UIImage imageNamed:@"user.png"], kSidebarCellTextKey: NSLocalizedString(@"Profile", @"")} 62 | ], 63 | @[ 64 | @{kSidebarCellImageKey: [UIImage imageNamed:@"user.png"], kSidebarCellTextKey: NSLocalizedString(@"News Feed", @"")}, 65 | @{kSidebarCellImageKey: [UIImage imageNamed:@"user.png"], kSidebarCellTextKey: NSLocalizedString(@"Messages", @"")}, 66 | @{kSidebarCellImageKey: [UIImage imageNamed:@"user.png"], kSidebarCellTextKey: NSLocalizedString(@"Nearby", @"")}, 67 | @{kSidebarCellImageKey: [UIImage imageNamed:@"user.png"], kSidebarCellTextKey: NSLocalizedString(@"Events", @"")}, 68 | @{kSidebarCellImageKey: [UIImage imageNamed:@"user.png"], kSidebarCellTextKey: NSLocalizedString(@"Friends", @"")}, 69 | ] 70 | ]; 71 | 72 | // Add drag feature to each root navigation controller 73 | [controllers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){ 74 | [((NSArray *)obj) enumerateObjectsUsingBlock:^(id obj2, NSUInteger idx2, BOOL *stop2){ 75 | UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self.revealController 76 | action:@selector(dragContentView:)]; 77 | panGesture.cancelsTouchesInView = YES; 78 | [((UINavigationController *)obj2).navigationBar addGestureRecognizer:panGesture]; 79 | }]; 80 | }]; 81 | 82 | self.searchController = [[GHSidebarSearchViewController alloc] initWithSidebarViewController:self.revealController]; 83 | self.searchController.view.backgroundColor = [UIColor clearColor]; 84 | self.searchController.searchDelegate = self; 85 | self.searchController.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone; 86 | self.searchController.searchBar.autocorrectionType = UITextAutocorrectionTypeNo; 87 | self.searchController.searchBar.backgroundImage = [UIImage imageNamed:@"searchBarBG.png"]; 88 | self.searchController.searchBar.placeholder = NSLocalizedString(@"Search", @""); 89 | self.searchController.searchBar.tintColor = [UIColor colorWithRed:(58.0f/255.0f) green:(67.0f/255.0f) blue:(104.0f/255.0f) alpha:1.0f]; 90 | for (UIView *subview in self.searchController.searchBar.subviews) { 91 | if ([subview isKindOfClass:[UITextField class]]) { 92 | UITextField *searchTextField = (UITextField *) subview; 93 | searchTextField.textColor = [UIColor colorWithRed:(154.0f/255.0f) green:(162.0f/255.0f) blue:(176.0f/255.0f) alpha:1.0f]; 94 | } 95 | } 96 | [self.searchController.searchBar setSearchFieldBackgroundImage:[[UIImage imageNamed:@"searchTextBG.png"] 97 | resizableImageWithCapInsets:UIEdgeInsetsMake(16.0f, 17.0f, 16.0f, 17.0f)] 98 | forState:UIControlStateNormal]; 99 | [self.searchController.searchBar setImage:[UIImage imageNamed:@"searchBarIcon.png"] 100 | forSearchBarIcon:UISearchBarIconSearch 101 | state:UIControlStateNormal]; 102 | 103 | self.menuController = [[GHMenuViewController alloc] initWithSidebarViewController:self.revealController 104 | withSearchBar:self.searchController.searchBar 105 | withHeaders:headers 106 | withControllers:controllers 107 | withCellInfos:cellInfos]; 108 | 109 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 110 | self.window.rootViewController = self.revealController; 111 | [self.window makeKeyAndVisible]; 112 | return YES; 113 | } 114 | 115 | #pragma mark GHSidebarSearchViewControllerDelegate 116 | - (void)searchResultsForText:(NSString *)text withScope:(NSString *)scope callback:(SearchResultsBlock)callback { 117 | callback(@[@"Foo", @"Bar", @"Baz"]); 118 | } 119 | 120 | - (void)searchResult:(id)result selectedAtIndexPath:(NSIndexPath *)indexPath { 121 | NSLog(@"Selected Search Result - result: %@ indexPath: %@", result, indexPath); 122 | } 123 | 124 | - (UITableViewCell *)searchResultCellForEntry:(id)entry atIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)tableView { 125 | static NSString* identifier = @"GHSearchMenuCell"; 126 | GHMenuCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier]; 127 | if (!cell) { 128 | cell = [[GHMenuCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; 129 | } 130 | cell.textLabel.text = (NSString *)entry; 131 | cell.imageView.image = [UIImage imageNamed:@"user"]; 132 | return cell; 133 | } 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /Demo/GHMenuCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHSidebarMenuCell.h 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | 9 | extern NSString const *kSidebarCellTextKey; 10 | extern NSString const *kSidebarCellImageKey; 11 | 12 | @interface GHMenuCell : UITableViewCell 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Demo/GHMenuCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHSidebarMenuCell.m 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | #import "GHMenuCell.h" 9 | 10 | 11 | #pragma mark - 12 | #pragma mark Constants 13 | NSString const *kSidebarCellTextKey = @"CellText"; 14 | NSString const *kSidebarCellImageKey = @"CellImage"; 15 | 16 | #pragma mark - 17 | #pragma mark Implementation 18 | @implementation GHMenuCell 19 | 20 | #pragma mark Memory Management 21 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 22 | if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { 23 | self.clipsToBounds = YES; 24 | self.backgroundColor = [UIColor clearColor]; 25 | 26 | UIView *bgView = [[UIView alloc] init]; 27 | bgView.backgroundColor = [UIColor colorWithRed:(38.0f/255.0f) green:(44.0f/255.0f) blue:(58.0f/255.0f) alpha:1.0f]; 28 | self.selectedBackgroundView = bgView; 29 | 30 | self.imageView.contentMode = UIViewContentModeCenter; 31 | 32 | self.textLabel.font = [UIFont fontWithName:@"Helvetica" size:([UIFont systemFontSize] * 1.2f)]; 33 | self.textLabel.shadowOffset = CGSizeMake(0.0f, 1.0f); 34 | self.textLabel.shadowColor = [UIColor colorWithWhite:0.0f alpha:0.25f]; 35 | self.textLabel.textColor = [UIColor colorWithRed:(196.0f/255.0f) green:(204.0f/255.0f) blue:(218.0f/255.0f) alpha:1.0f]; 36 | 37 | UIView *topLine = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [UIScreen mainScreen].bounds.size.height, 1.0f)]; 38 | topLine.backgroundColor = [UIColor colorWithRed:(54.0f/255.0f) green:(61.0f/255.0f) blue:(76.0f/255.0f) alpha:1.0f]; 39 | [self.textLabel.superview addSubview:topLine]; 40 | 41 | UIView *topLine2 = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 1.0f, [UIScreen mainScreen].bounds.size.height, 1.0f)]; 42 | topLine2.backgroundColor = [UIColor colorWithRed:(54.0f/255.0f) green:(61.0f/255.0f) blue:(77.0f/255.0f) alpha:1.0f]; 43 | [self.textLabel.superview addSubview:topLine2]; 44 | 45 | UIView *bottomLine = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 43.0f, [UIScreen mainScreen].bounds.size.height, 1.0f)]; 46 | bottomLine.backgroundColor = [UIColor colorWithRed:(40.0f/255.0f) green:(47.0f/255.0f) blue:(61.0f/255.0f) alpha:1.0f]; 47 | [self.textLabel.superview addSubview:bottomLine]; 48 | } 49 | return self; 50 | } 51 | 52 | #pragma mark UIView 53 | - (void)layoutSubviews { 54 | [super layoutSubviews]; 55 | self.textLabel.frame = CGRectMake(50.0f, 0.0f, 200.0f, 43.0f); 56 | self.imageView.frame = CGRectMake(0.0f, 0.0f, 50.0f, 43.0f); 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Demo/GHMenuViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHMenuViewController.h 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 1/3/12. 6 | // Copyright (c) 2012 Greg Haines. All rights reserved. 7 | // 8 | 9 | @class GHRevealViewController; 10 | 11 | 12 | @interface GHMenuViewController : UIViewController 13 | 14 | - (id)initWithSidebarViewController:(GHRevealViewController *)sidebarVC 15 | withSearchBar:(UISearchBar *)searchBar 16 | withHeaders:(NSArray *)headers 17 | withControllers:(NSArray *)controllers 18 | withCellInfos:(NSArray *)cellInfos; 19 | 20 | - (void)selectRowAtIndexPath:(NSIndexPath *)indexPath 21 | animated:(BOOL)animated 22 | scrollPosition:(UITableViewScrollPosition)scrollPosition; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Demo/GHMenuViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHMenuViewController.m 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 1/3/12. 6 | // Copyright (c) 2012 Greg Haines. All rights reserved. 7 | // 8 | 9 | #import "GHMenuViewController.h" 10 | #import "GHMenuCell.h" 11 | #import "GHRevealViewController.h" 12 | #import 13 | 14 | 15 | #pragma mark - 16 | #pragma mark Implementation 17 | @implementation GHMenuViewController { 18 | GHRevealViewController *_sidebarVC; 19 | UISearchBar *_searchBar; 20 | UITableView *_menuTableView; 21 | NSArray *_headers; 22 | NSArray *_controllers; 23 | NSArray *_cellInfos; 24 | } 25 | 26 | #pragma mark Memory Management 27 | - (id)initWithSidebarViewController:(GHRevealViewController *)sidebarVC 28 | withSearchBar:(UISearchBar *)searchBar 29 | withHeaders:(NSArray *)headers 30 | withControllers:(NSArray *)controllers 31 | withCellInfos:(NSArray *)cellInfos { 32 | if (self = [super initWithNibName:nil bundle:nil]) { 33 | _sidebarVC = sidebarVC; 34 | _searchBar = searchBar; 35 | _headers = headers; 36 | _controllers = controllers; 37 | _cellInfos = cellInfos; 38 | 39 | _sidebarVC.sidebarViewController = self; 40 | _sidebarVC.contentViewController = _controllers[0][0]; 41 | } 42 | return self; 43 | } 44 | 45 | #pragma mark UIViewController 46 | - (void)viewDidLoad { 47 | [super viewDidLoad]; 48 | self.view.frame = CGRectMake(0.0f, 0.0f, kGHRevealSidebarWidth, CGRectGetHeight(self.view.bounds)); 49 | self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight; 50 | 51 | [self.view addSubview:_searchBar]; 52 | 53 | _menuTableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0f, 44.0f, kGHRevealSidebarWidth, CGRectGetHeight(self.view.bounds) - 44.0f) 54 | style:UITableViewStylePlain]; 55 | _menuTableView.delegate = self; 56 | _menuTableView.dataSource = self; 57 | _menuTableView.autoresizingMask = UIViewAutoresizingFlexibleHeight; 58 | _menuTableView.backgroundColor = [UIColor clearColor]; 59 | _menuTableView.separatorStyle = UITableViewCellSeparatorStyleNone; 60 | [self.view addSubview:_menuTableView]; 61 | [self selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop]; 62 | } 63 | 64 | - (void)viewWillAppear:(BOOL)animated { 65 | self.view.frame = CGRectMake(0.0f, 0.0f,kGHRevealSidebarWidth, CGRectGetHeight(self.view.bounds)); 66 | [_searchBar sizeToFit]; 67 | } 68 | 69 | - (void)viewDidLayoutSubviews { 70 | if ([self respondsToSelector:@selector(topLayoutGuide)]) { 71 | CGRect viewBounds = self.view.frame; 72 | CGFloat topBarOffset = self.topLayoutGuide.length; 73 | self.view.frame = CGRectMake(viewBounds.origin.x, topBarOffset, 74 | viewBounds.size.width, viewBounds.size.height); 75 | } 76 | } 77 | 78 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation { 79 | return (orientation == UIInterfaceOrientationPortraitUpsideDown) 80 | ? (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 81 | : YES; 82 | } 83 | 84 | #pragma mark UITableViewDataSource 85 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 86 | return _headers.count; 87 | } 88 | 89 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 90 | return ((NSArray *)_cellInfos[section]).count; 91 | } 92 | 93 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 94 | static NSString *CellIdentifier = @"GHMenuCell"; 95 | GHMenuCell *cell = (GHMenuCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 96 | if (cell == nil) { 97 | cell = [[GHMenuCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 98 | } 99 | NSDictionary *info = _cellInfos[indexPath.section][indexPath.row]; 100 | cell.textLabel.text = info[kSidebarCellTextKey]; 101 | cell.imageView.image = info[kSidebarCellImageKey]; 102 | return cell; 103 | } 104 | 105 | #pragma mark UITableViewDelegate 106 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 107 | return (_headers[section] == [NSNull null]) ? 0.0f : 21.0f; 108 | } 109 | 110 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 111 | NSObject *headerText = _headers[section]; 112 | UIView *headerView = nil; 113 | if (headerText != [NSNull null]) { 114 | headerView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [UIScreen mainScreen].bounds.size.height, 21.0f)]; 115 | CAGradientLayer *gradient = [CAGradientLayer layer]; 116 | gradient.frame = headerView.bounds; 117 | gradient.colors = @[ 118 | (id)[UIColor colorWithRed:(67.0f/255.0f) green:(74.0f/255.0f) blue:(94.0f/255.0f) alpha:1.0f].CGColor, 119 | (id)[UIColor colorWithRed:(57.0f/255.0f) green:(64.0f/255.0f) blue:(82.0f/255.0f) alpha:1.0f].CGColor, 120 | ]; 121 | [headerView.layer insertSublayer:gradient atIndex:0]; 122 | 123 | UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectInset(headerView.bounds, 12.0f, 5.0f)]; 124 | textLabel.text = (NSString *) headerText; 125 | textLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:([UIFont systemFontSize] * 0.8f)]; 126 | textLabel.shadowOffset = CGSizeMake(0.0f, 1.0f); 127 | textLabel.shadowColor = [UIColor colorWithWhite:0.0f alpha:0.25f]; 128 | textLabel.textColor = [UIColor colorWithRed:(125.0f/255.0f) green:(129.0f/255.0f) blue:(146.0f/255.0f) alpha:1.0f]; 129 | textLabel.backgroundColor = [UIColor clearColor]; 130 | [headerView addSubview:textLabel]; 131 | 132 | UIView *topLine = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [UIScreen mainScreen].bounds.size.height, 1.0f)]; 133 | topLine.backgroundColor = [UIColor colorWithRed:(78.0f/255.0f) green:(86.0f/255.0f) blue:(103.0f/255.0f) alpha:1.0f]; 134 | [headerView addSubview:topLine]; 135 | 136 | UIView *bottomLine = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 21.0f, [UIScreen mainScreen].bounds.size.height, 1.0f)]; 137 | bottomLine.backgroundColor = [UIColor colorWithRed:(36.0f/255.0f) green:(42.0f/255.0f) blue:(5.0f/255.0f) alpha:1.0f]; 138 | [headerView addSubview:bottomLine]; 139 | } 140 | return headerView; 141 | } 142 | 143 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 144 | _sidebarVC.contentViewController = _controllers[indexPath.section][indexPath.row]; 145 | [_sidebarVC toggleSidebar:NO duration:kGHRevealSidebarDefaultAnimationDuration]; 146 | } 147 | 148 | #pragma mark Public Methods 149 | - (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition { 150 | [_menuTableView selectRowAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; 151 | if (scrollPosition == UITableViewScrollPositionNone) { 152 | [_menuTableView scrollToRowAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated]; 153 | } 154 | _sidebarVC.contentViewController = _controllers[indexPath.section][indexPath.row]; 155 | } 156 | 157 | @end 158 | -------------------------------------------------------------------------------- /Demo/GHPushedViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHPushedViewController.h 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/29/11. 6 | // 7 | 8 | 9 | @interface GHPushedViewController : UIViewController 10 | 11 | - (id)initWithTitle:(NSString *)title; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Demo/GHPushedViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHPushedViewController.m 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/29/11. 6 | // 7 | 8 | #import "GHPushedViewController.h" 9 | 10 | 11 | #pragma mark Implementation 12 | @implementation GHPushedViewController 13 | 14 | #pragma mark Memory Management 15 | - (id)initWithTitle:(NSString *)title { 16 | if (self = [super initWithNibName:nil bundle:nil]) { 17 | self.title = title; 18 | } 19 | return self; 20 | } 21 | 22 | #pragma mark UIViewController 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | self.view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); 26 | UIView *view = [[UIView alloc] initWithFrame:self.view.bounds]; 27 | view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); 28 | view.backgroundColor = [UIColor redColor]; 29 | [self.view addSubview:view]; 30 | if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) { 31 | self.edgesForExtendedLayout = UIRectEdgeNone; 32 | } 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Demo/GHRootViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHRootViewController.h 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | 9 | typedef void (^RevealBlock)(); 10 | 11 | @interface GHRootViewController : UIViewController 12 | 13 | - (id)initWithTitle:(NSString *)title withRevealBlock:(RevealBlock)revealBlock; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Demo/GHRootViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHRootViewController.m 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | #import "GHRootViewController.h" 9 | #import "GHPushedViewController.h" 10 | 11 | 12 | #pragma mark Private Interface 13 | @interface GHRootViewController () 14 | - (void)pushViewController; 15 | - (void)revealSidebar; 16 | @end 17 | 18 | #pragma mark Implementation 19 | @implementation GHRootViewController{ 20 | @private 21 | RevealBlock _revealBlock; 22 | } 23 | 24 | #pragma mark Memory Management 25 | - (id)initWithTitle:(NSString *)title withRevealBlock:(RevealBlock)revealBlock { 26 | if (self = [super initWithNibName:nil bundle:nil]) { 27 | self.title = title; 28 | _revealBlock = [revealBlock copy]; 29 | self.navigationItem.leftBarButtonItem = 30 | [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction 31 | target:self 32 | action:@selector(revealSidebar)]; 33 | } 34 | return self; 35 | } 36 | 37 | #pragma mark UIViewController 38 | - (void)viewDidLoad { 39 | [super viewDidLoad]; 40 | self.view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); 41 | self.view.backgroundColor = [UIColor lightGrayColor]; 42 | UIButton *pushButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 43 | [pushButton setTitle:@"Push" forState:UIControlStateNormal]; 44 | [pushButton addTarget:self action:@selector(pushViewController) forControlEvents:UIControlEventTouchUpInside]; 45 | [pushButton sizeToFit]; 46 | [self.view addSubview:pushButton]; 47 | if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) { 48 | self.edgesForExtendedLayout = UIRectEdgeNone; 49 | } 50 | } 51 | 52 | #pragma mark Private Methods 53 | - (void)pushViewController { 54 | NSString *vcTitle = [self.title stringByAppendingString:@" - Pushed"]; 55 | UIViewController *vc = [[GHPushedViewController alloc] initWithTitle:vcTitle]; 56 | [self.navigationController pushViewController:vc animated:YES]; 57 | } 58 | 59 | - (void)revealSidebar { 60 | _revealBlock(); 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Demo/GHSidebarNav-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | UIStatusBarStyle 8 | UIStatusBarStyleBlackTranslucent 9 | CFBundleDisplayName 10 | ${PRODUCT_NAME} 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIconFiles 14 | 15 | CFBundleIdentifier 16 | net.greghaines.${PRODUCT_NAME:rfc1034identifier} 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | ${PRODUCT_NAME} 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 1.0 25 | CFBundleSignature 26 | GREG 27 | CFBundleVersion 28 | 1.0 29 | LSRequiresIPhoneOS 30 | 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Demo/GHSidebarNav-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'GHSidebarNav' target in the 'GHSidebarNav' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_6_0 8 | #warning "This project uses features only available in iOS SDK 6.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /Demo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | #import "GHAppDelegate.h" 9 | 10 | 11 | int main(int argc, char *argv[]) { 12 | @autoreleasepool { 13 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([GHAppDelegate class])); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GHSidebarNav.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "GHSidebarNav" 3 | s.version = "1.0.0" 4 | s.summary = "A clone of the new Facebook iOS UI paradigm." 5 | s.description = <<-DESC 6 | A clone of the new Facebook iOS UI paradigm; a sidebar navigation table that is revealed by sliding the main content panel to the right. The search goes full-screen and everything supports the standard orientations. 7 | 8 | This project uses the Container View Controller methods introduced in iOS 5.0 so, it won't work on any version prior. 9 | This project uses ARC so, you'll need Mac OS 10.7+ (Lion) and Xcode 4.2.1+ to build it. 10 | DESC 11 | s.homepage = "https://github.com/gresrun/GHSidebarNav" 12 | 13 | s.license = { :type => 'Apache License, Version 2.0 ', :file => 'LICENSE' } 14 | s.author = { "Gregory Haines" => "greg@greghaines.net" } 15 | s.source = { :git => "https://github.com/gresrun/GHSidebarNav.git", :commit => :head } 16 | s.source_files = 'NSObject+Subscripts.h', 'GHSidebarNav/**/*.{h,m}' 17 | s.platform = :ios, '5.0' 18 | 19 | s.resources = "GHSidebarNav/Images/*.png" 20 | s.requires_arc = true 21 | 22 | s.prefix_header_contents = %{#ifdef __OBJC__\n#import "NSObject+Subscripts.h"\n#endif} 23 | end 24 | -------------------------------------------------------------------------------- /GHSidebarNav.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 372EED28166FE3B60067C395 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 372EED27166FE3B60067C395 /* Default-568h@2x.png */; }; 11 | 6B014F5214B3DAC4001E922B /* GHMenuViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B014F5114B3DAC4001E922B /* GHMenuViewController.m */; }; 12 | 6B014F5714B41DB6001E922B /* GHSidebarSearchViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B014F5614B41DB6001E922B /* GHSidebarSearchViewController.m */; }; 13 | 6B0CAC0114BD064800394B5D /* searchBarIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 6B0CABFE14BD064800394B5D /* searchBarIcon.png */; }; 14 | 6B0CAC0214BD064800394B5D /* searchBarIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6B0CABFF14BD064800394B5D /* searchBarIcon@2x.png */; }; 15 | 6B0CAC0314BD064800394B5D /* searchTextBG.png in Resources */ = {isa = PBXBuildFile; fileRef = 6B0CAC0014BD064800394B5D /* searchTextBG.png */; }; 16 | 6B4BD80214B10447004BE0CC /* GHMenuCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B4BD80114B10447004BE0CC /* GHMenuCell.m */; }; 17 | 6BBA75C014873DFE004E1A5E /* GHAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BBA75BB14873DFD004E1A5E /* GHAppDelegate.m */; }; 18 | 6BBA75C114873DFE004E1A5E /* GHPushedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BBA75BD14873DFD004E1A5E /* GHPushedViewController.m */; }; 19 | 6BBA75C214873DFE004E1A5E /* GHRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BBA75BF14873DFD004E1A5E /* GHRootViewController.m */; }; 20 | 6BBA75C914873E18004E1A5E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6BBA75C414873E18004E1A5E /* InfoPlist.strings */; }; 21 | 6BBA75CB14873E18004E1A5E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BBA75C814873E18004E1A5E /* main.m */; }; 22 | 6BBA75CE14873E74004E1A5E /* searchBarBG.png in Resources */ = {isa = PBXBuildFile; fileRef = 6BBA75CC14873E74004E1A5E /* searchBarBG.png */; }; 23 | 6BBA75CF14873E74004E1A5E /* user.png in Resources */ = {isa = PBXBuildFile; fileRef = 6BBA75CD14873E74004E1A5E /* user.png */; }; 24 | 6BE3FCA9147A096500CDEC04 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BE3FCA8147A096500CDEC04 /* UIKit.framework */; }; 25 | 6BE3FCAB147A096500CDEC04 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BE3FCAA147A096500CDEC04 /* Foundation.framework */; }; 26 | 6BE3FCAD147A096500CDEC04 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BE3FCAC147A096500CDEC04 /* CoreGraphics.framework */; }; 27 | 6BE3FCC4147A09E400CDEC04 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BE3FCC3147A09E400CDEC04 /* QuartzCore.framework */; }; 28 | 6BE3FCDA147A118200CDEC04 /* GHRevealViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BE3FCD6147A118200CDEC04 /* GHRevealViewController.m */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 372EED27166FE3B60067C395 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 33 | 6B014F5014B3DAC4001E922B /* GHMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GHMenuViewController.h; path = Demo/GHMenuViewController.h; sourceTree = SOURCE_ROOT; }; 34 | 6B014F5114B3DAC4001E922B /* GHMenuViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GHMenuViewController.m; path = Demo/GHMenuViewController.m; sourceTree = SOURCE_ROOT; }; 35 | 6B014F5514B41DB6001E922B /* GHSidebarSearchViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHSidebarSearchViewController.h; sourceTree = ""; }; 36 | 6B014F5614B41DB6001E922B /* GHSidebarSearchViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHSidebarSearchViewController.m; sourceTree = ""; }; 37 | 6B0CABFE14BD064800394B5D /* searchBarIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = searchBarIcon.png; path = Images/searchBarIcon.png; sourceTree = ""; }; 38 | 6B0CABFF14BD064800394B5D /* searchBarIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "searchBarIcon@2x.png"; path = "Images/searchBarIcon@2x.png"; sourceTree = ""; }; 39 | 6B0CAC0014BD064800394B5D /* searchTextBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = searchTextBG.png; path = Images/searchTextBG.png; sourceTree = ""; }; 40 | 6B4BD80014B10447004BE0CC /* GHMenuCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GHMenuCell.h; path = Demo/GHMenuCell.h; sourceTree = SOURCE_ROOT; }; 41 | 6B4BD80114B10447004BE0CC /* GHMenuCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GHMenuCell.m; path = Demo/GHMenuCell.m; sourceTree = SOURCE_ROOT; }; 42 | 6B71B28C14B8C98E00588FB6 /* GHSidebarSearchViewControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHSidebarSearchViewControllerDelegate.h; sourceTree = ""; }; 43 | 6BBA75BA14873DFD004E1A5E /* GHAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GHAppDelegate.h; path = Demo/GHAppDelegate.h; sourceTree = SOURCE_ROOT; }; 44 | 6BBA75BB14873DFD004E1A5E /* GHAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GHAppDelegate.m; path = Demo/GHAppDelegate.m; sourceTree = SOURCE_ROOT; }; 45 | 6BBA75BC14873DFD004E1A5E /* GHPushedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GHPushedViewController.h; path = Demo/GHPushedViewController.h; sourceTree = SOURCE_ROOT; }; 46 | 6BBA75BD14873DFD004E1A5E /* GHPushedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GHPushedViewController.m; path = Demo/GHPushedViewController.m; sourceTree = SOURCE_ROOT; }; 47 | 6BBA75BE14873DFD004E1A5E /* GHRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GHRootViewController.h; path = Demo/GHRootViewController.h; sourceTree = SOURCE_ROOT; }; 48 | 6BBA75BF14873DFD004E1A5E /* GHRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GHRootViewController.m; path = Demo/GHRootViewController.m; sourceTree = SOURCE_ROOT; }; 49 | 6BBA75C514873E18004E1A5E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; 50 | 6BBA75C614873E18004E1A5E /* GHSidebarNav-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GHSidebarNav-Info.plist"; path = "Demo/GHSidebarNav-Info.plist"; sourceTree = SOURCE_ROOT; }; 51 | 6BBA75C714873E18004E1A5E /* GHSidebarNav-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GHSidebarNav-Prefix.pch"; path = "Demo/GHSidebarNav-Prefix.pch"; sourceTree = SOURCE_ROOT; }; 52 | 6BBA75C814873E18004E1A5E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Demo/main.m; sourceTree = SOURCE_ROOT; }; 53 | 6BBA75CC14873E74004E1A5E /* searchBarBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = searchBarBG.png; path = Images/searchBarBG.png; sourceTree = ""; }; 54 | 6BBA75CD14873E74004E1A5E /* user.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = user.png; path = Images/user.png; sourceTree = ""; }; 55 | 6BE3FCA4147A096500CDEC04 /* GHSidebarNav.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GHSidebarNav.app; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 6BE3FCA8147A096500CDEC04 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 57 | 6BE3FCAA147A096500CDEC04 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 58 | 6BE3FCAC147A096500CDEC04 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 59 | 6BE3FCC3147A09E400CDEC04 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 60 | 6BE3FCD5147A118100CDEC04 /* GHRevealViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHRevealViewController.h; sourceTree = ""; }; 61 | 6BE3FCD6147A118200CDEC04 /* GHRevealViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHRevealViewController.m; sourceTree = ""; }; 62 | /* End PBXFileReference section */ 63 | 64 | /* Begin PBXFrameworksBuildPhase section */ 65 | 6BE3FCA1147A096500CDEC04 /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | 6BE3FCC4147A09E400CDEC04 /* QuartzCore.framework in Frameworks */, 70 | 6BE3FCA9147A096500CDEC04 /* UIKit.framework in Frameworks */, 71 | 6BE3FCAB147A096500CDEC04 /* Foundation.framework in Frameworks */, 72 | 6BE3FCAD147A096500CDEC04 /* CoreGraphics.framework in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 6BBA75B914872E10004E1A5E /* Demo */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 6BBA75BA14873DFD004E1A5E /* GHAppDelegate.h */, 83 | 6BBA75BB14873DFD004E1A5E /* GHAppDelegate.m */, 84 | 6B4BD80014B10447004BE0CC /* GHMenuCell.h */, 85 | 6B4BD80114B10447004BE0CC /* GHMenuCell.m */, 86 | 6B014F5014B3DAC4001E922B /* GHMenuViewController.h */, 87 | 6B014F5114B3DAC4001E922B /* GHMenuViewController.m */, 88 | 6BBA75BC14873DFD004E1A5E /* GHPushedViewController.h */, 89 | 6BBA75BD14873DFD004E1A5E /* GHPushedViewController.m */, 90 | 6BBA75BE14873DFD004E1A5E /* GHRootViewController.h */, 91 | 6BBA75BF14873DFD004E1A5E /* GHRootViewController.m */, 92 | 6BE3FCAF147A096500CDEC04 /* Supporting Files */, 93 | ); 94 | name = Demo; 95 | path = GHSidebarNav/GHSidebarNavDemo; 96 | sourceTree = ""; 97 | }; 98 | 6BBA75C314873E18004E1A5E /* en.lproj */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 6BBA75C414873E18004E1A5E /* InfoPlist.strings */, 102 | ); 103 | name = en.lproj; 104 | path = Demo/en.lproj; 105 | sourceTree = SOURCE_ROOT; 106 | }; 107 | 6BE3FC99147A096400CDEC04 = { 108 | isa = PBXGroup; 109 | children = ( 110 | 372EED27166FE3B60067C395 /* Default-568h@2x.png */, 111 | 6BE3FCAE147A096500CDEC04 /* GHSidebarNav */, 112 | 6BBA75B914872E10004E1A5E /* Demo */, 113 | 6BE3FCCA147A115600CDEC04 /* Resources */, 114 | 6BE3FCA7147A096500CDEC04 /* Frameworks */, 115 | 6BE3FCA5147A096500CDEC04 /* Products */, 116 | ); 117 | sourceTree = ""; 118 | }; 119 | 6BE3FCA5147A096500CDEC04 /* Products */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 6BE3FCA4147A096500CDEC04 /* GHSidebarNav.app */, 123 | ); 124 | name = Products; 125 | sourceTree = ""; 126 | }; 127 | 6BE3FCA7147A096500CDEC04 /* Frameworks */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 6BE3FCC3147A09E400CDEC04 /* QuartzCore.framework */, 131 | 6BE3FCA8147A096500CDEC04 /* UIKit.framework */, 132 | 6BE3FCAA147A096500CDEC04 /* Foundation.framework */, 133 | 6BE3FCAC147A096500CDEC04 /* CoreGraphics.framework */, 134 | ); 135 | name = Frameworks; 136 | sourceTree = ""; 137 | }; 138 | 6BE3FCAE147A096500CDEC04 /* GHSidebarNav */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 6BE3FCD5147A118100CDEC04 /* GHRevealViewController.h */, 142 | 6BE3FCD6147A118200CDEC04 /* GHRevealViewController.m */, 143 | 6B014F5514B41DB6001E922B /* GHSidebarSearchViewController.h */, 144 | 6B014F5614B41DB6001E922B /* GHSidebarSearchViewController.m */, 145 | 6B71B28C14B8C98E00588FB6 /* GHSidebarSearchViewControllerDelegate.h */, 146 | ); 147 | path = GHSidebarNav; 148 | sourceTree = ""; 149 | }; 150 | 6BE3FCAF147A096500CDEC04 /* Supporting Files */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 6BBA75C314873E18004E1A5E /* en.lproj */, 154 | 6BBA75C614873E18004E1A5E /* GHSidebarNav-Info.plist */, 155 | 6BBA75C714873E18004E1A5E /* GHSidebarNav-Prefix.pch */, 156 | 6BBA75C814873E18004E1A5E /* main.m */, 157 | ); 158 | name = "Supporting Files"; 159 | path = ..; 160 | sourceTree = ""; 161 | }; 162 | 6BE3FCCA147A115600CDEC04 /* Resources */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | 6BBA75CC14873E74004E1A5E /* searchBarBG.png */, 166 | 6B0CABFE14BD064800394B5D /* searchBarIcon.png */, 167 | 6B0CABFF14BD064800394B5D /* searchBarIcon@2x.png */, 168 | 6B0CAC0014BD064800394B5D /* searchTextBG.png */, 169 | 6BBA75CD14873E74004E1A5E /* user.png */, 170 | ); 171 | name = Resources; 172 | path = GHSidebarNav; 173 | sourceTree = ""; 174 | }; 175 | /* End PBXGroup section */ 176 | 177 | /* Begin PBXNativeTarget section */ 178 | 6BE3FCA3147A096500CDEC04 /* GHSidebarNav */ = { 179 | isa = PBXNativeTarget; 180 | buildConfigurationList = 6BE3FCBC147A096500CDEC04 /* Build configuration list for PBXNativeTarget "GHSidebarNav" */; 181 | buildPhases = ( 182 | 6BE3FCA0147A096500CDEC04 /* Sources */, 183 | 6BE3FCA1147A096500CDEC04 /* Frameworks */, 184 | 6BE3FCA2147A096500CDEC04 /* Resources */, 185 | ); 186 | buildRules = ( 187 | ); 188 | dependencies = ( 189 | ); 190 | name = GHSidebarNav; 191 | productName = GHSidebarNav; 192 | productReference = 6BE3FCA4147A096500CDEC04 /* GHSidebarNav.app */; 193 | productType = "com.apple.product-type.application"; 194 | }; 195 | /* End PBXNativeTarget section */ 196 | 197 | /* Begin PBXProject section */ 198 | 6BE3FC9B147A096400CDEC04 /* Project object */ = { 199 | isa = PBXProject; 200 | attributes = { 201 | LastUpgradeCheck = 0500; 202 | }; 203 | buildConfigurationList = 6BE3FC9E147A096400CDEC04 /* Build configuration list for PBXProject "GHSidebarNav" */; 204 | compatibilityVersion = "Xcode 3.2"; 205 | developmentRegion = English; 206 | hasScannedForEncodings = 0; 207 | knownRegions = ( 208 | en, 209 | ); 210 | mainGroup = 6BE3FC99147A096400CDEC04; 211 | productRefGroup = 6BE3FCA5147A096500CDEC04 /* Products */; 212 | projectDirPath = ""; 213 | projectRoot = ""; 214 | targets = ( 215 | 6BE3FCA3147A096500CDEC04 /* GHSidebarNav */, 216 | ); 217 | }; 218 | /* End PBXProject section */ 219 | 220 | /* Begin PBXResourcesBuildPhase section */ 221 | 6BE3FCA2147A096500CDEC04 /* Resources */ = { 222 | isa = PBXResourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | 6BBA75C914873E18004E1A5E /* InfoPlist.strings in Resources */, 226 | 6BBA75CE14873E74004E1A5E /* searchBarBG.png in Resources */, 227 | 6BBA75CF14873E74004E1A5E /* user.png in Resources */, 228 | 6B0CAC0114BD064800394B5D /* searchBarIcon.png in Resources */, 229 | 6B0CAC0214BD064800394B5D /* searchBarIcon@2x.png in Resources */, 230 | 6B0CAC0314BD064800394B5D /* searchTextBG.png in Resources */, 231 | 372EED28166FE3B60067C395 /* Default-568h@2x.png in Resources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXResourcesBuildPhase section */ 236 | 237 | /* Begin PBXSourcesBuildPhase section */ 238 | 6BE3FCA0147A096500CDEC04 /* Sources */ = { 239 | isa = PBXSourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | 6BE3FCDA147A118200CDEC04 /* GHRevealViewController.m in Sources */, 243 | 6BBA75C014873DFE004E1A5E /* GHAppDelegate.m in Sources */, 244 | 6BBA75C114873DFE004E1A5E /* GHPushedViewController.m in Sources */, 245 | 6BBA75C214873DFE004E1A5E /* GHRootViewController.m in Sources */, 246 | 6BBA75CB14873E18004E1A5E /* main.m in Sources */, 247 | 6B4BD80214B10447004BE0CC /* GHMenuCell.m in Sources */, 248 | 6B014F5214B3DAC4001E922B /* GHMenuViewController.m in Sources */, 249 | 6B014F5714B41DB6001E922B /* GHSidebarSearchViewController.m in Sources */, 250 | ); 251 | runOnlyForDeploymentPostprocessing = 0; 252 | }; 253 | /* End PBXSourcesBuildPhase section */ 254 | 255 | /* Begin PBXVariantGroup section */ 256 | 6BBA75C414873E18004E1A5E /* InfoPlist.strings */ = { 257 | isa = PBXVariantGroup; 258 | children = ( 259 | 6BBA75C514873E18004E1A5E /* en */, 260 | ); 261 | name = InfoPlist.strings; 262 | sourceTree = ""; 263 | }; 264 | /* End PBXVariantGroup section */ 265 | 266 | /* Begin XCBuildConfiguration section */ 267 | 6BE3FCBA147A096500CDEC04 /* Debug */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | ALWAYS_SEARCH_USER_PATHS = NO; 271 | CLANG_ENABLE_OBJC_ARC = YES; 272 | CLANG_WARN_BOOL_CONVERSION = YES; 273 | CLANG_WARN_CONSTANT_CONVERSION = YES; 274 | CLANG_WARN_EMPTY_BODY = YES; 275 | CLANG_WARN_ENUM_CONVERSION = YES; 276 | CLANG_WARN_INT_CONVERSION = YES; 277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 278 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 279 | COPY_PHASE_STRIP = NO; 280 | GCC_C_LANGUAGE_STANDARD = gnu99; 281 | GCC_OPTIMIZATION_LEVEL = 0; 282 | GCC_PREPROCESSOR_DEFINITIONS = ( 283 | "DEBUG=1", 284 | "$(inherited)", 285 | ); 286 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 287 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 288 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 289 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 290 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 291 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 292 | GCC_WARN_PEDANTIC = YES; 293 | GCC_WARN_SHADOW = YES; 294 | GCC_WARN_SIGN_COMPARE = YES; 295 | GCC_WARN_UNDECLARED_SELECTOR = YES; 296 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 297 | GCC_WARN_UNUSED_FUNCTION = YES; 298 | GCC_WARN_UNUSED_LABEL = YES; 299 | GCC_WARN_UNUSED_PARAMETER = NO; 300 | GCC_WARN_UNUSED_VARIABLE = YES; 301 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 302 | ONLY_ACTIVE_ARCH = YES; 303 | RUN_CLANG_STATIC_ANALYZER = YES; 304 | SDKROOT = iphoneos; 305 | TARGETED_DEVICE_FAMILY = "1,2"; 306 | }; 307 | name = Debug; 308 | }; 309 | 6BE3FCBB147A096500CDEC04 /* Release */ = { 310 | isa = XCBuildConfiguration; 311 | buildSettings = { 312 | ALWAYS_SEARCH_USER_PATHS = NO; 313 | CLANG_ENABLE_OBJC_ARC = YES; 314 | CLANG_WARN_BOOL_CONVERSION = YES; 315 | CLANG_WARN_CONSTANT_CONVERSION = YES; 316 | CLANG_WARN_EMPTY_BODY = YES; 317 | CLANG_WARN_ENUM_CONVERSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 320 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 321 | COPY_PHASE_STRIP = YES; 322 | GCC_C_LANGUAGE_STANDARD = gnu99; 323 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 324 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 325 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 326 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 327 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 328 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 329 | GCC_WARN_PEDANTIC = YES; 330 | GCC_WARN_SHADOW = YES; 331 | GCC_WARN_SIGN_COMPARE = YES; 332 | GCC_WARN_UNDECLARED_SELECTOR = YES; 333 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 334 | GCC_WARN_UNUSED_FUNCTION = YES; 335 | GCC_WARN_UNUSED_LABEL = YES; 336 | GCC_WARN_UNUSED_PARAMETER = NO; 337 | GCC_WARN_UNUSED_VARIABLE = YES; 338 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 339 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 340 | RUN_CLANG_STATIC_ANALYZER = YES; 341 | SDKROOT = iphoneos; 342 | TARGETED_DEVICE_FAMILY = "1,2"; 343 | VALIDATE_PRODUCT = YES; 344 | }; 345 | name = Release; 346 | }; 347 | 6BE3FCBD147A096500CDEC04 /* Debug */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 351 | GCC_PREFIX_HEADER = "Demo/GHSidebarNav-Prefix.pch"; 352 | INFOPLIST_FILE = "Demo/GHSidebarNav-Info.plist"; 353 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 354 | PRODUCT_NAME = "$(TARGET_NAME)"; 355 | WRAPPER_EXTENSION = app; 356 | }; 357 | name = Debug; 358 | }; 359 | 6BE3FCBE147A096500CDEC04 /* Release */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 363 | GCC_PREFIX_HEADER = "Demo/GHSidebarNav-Prefix.pch"; 364 | INFOPLIST_FILE = "Demo/GHSidebarNav-Info.plist"; 365 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 366 | PRODUCT_NAME = "$(TARGET_NAME)"; 367 | WRAPPER_EXTENSION = app; 368 | }; 369 | name = Release; 370 | }; 371 | /* End XCBuildConfiguration section */ 372 | 373 | /* Begin XCConfigurationList section */ 374 | 6BE3FC9E147A096400CDEC04 /* Build configuration list for PBXProject "GHSidebarNav" */ = { 375 | isa = XCConfigurationList; 376 | buildConfigurations = ( 377 | 6BE3FCBA147A096500CDEC04 /* Debug */, 378 | 6BE3FCBB147A096500CDEC04 /* Release */, 379 | ); 380 | defaultConfigurationIsVisible = 0; 381 | defaultConfigurationName = Release; 382 | }; 383 | 6BE3FCBC147A096500CDEC04 /* Build configuration list for PBXNativeTarget "GHSidebarNav" */ = { 384 | isa = XCConfigurationList; 385 | buildConfigurations = ( 386 | 6BE3FCBD147A096500CDEC04 /* Debug */, 387 | 6BE3FCBE147A096500CDEC04 /* Release */, 388 | ); 389 | defaultConfigurationIsVisible = 0; 390 | defaultConfigurationName = Release; 391 | }; 392 | /* End XCConfigurationList section */ 393 | }; 394 | rootObject = 6BE3FC9B147A096400CDEC04 /* Project object */; 395 | } 396 | -------------------------------------------------------------------------------- /GHSidebarNav/GHRevealViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHSidebarViewController.h 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | 9 | extern const NSTimeInterval kGHRevealSidebarDefaultAnimationDuration; 10 | extern const CGFloat kGHRevealSidebarWidth; 11 | 12 | @interface GHRevealViewController : UIViewController 13 | 14 | @property (nonatomic, readonly, getter = isSidebarShowing) BOOL sidebarShowing; 15 | @property (nonatomic, readonly, getter = isSearching) BOOL searching; 16 | @property (strong, nonatomic) UIViewController *sidebarViewController; 17 | @property (strong, nonatomic) UIViewController *contentViewController; 18 | 19 | - (void)dragContentView:(UIPanGestureRecognizer *)panGesture; 20 | - (void)toggleSidebar:(BOOL)show duration:(NSTimeInterval)duration; 21 | - (void)toggleSidebar:(BOOL)show duration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion; 22 | - (void)toggleSearch:(BOOL)showSearch withSearchView:(UIView *)searchView duration:(NSTimeInterval)duration; 23 | - (void)toggleSearch:(BOOL)showSearch withSearchView:(UIView *)searchView duration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /GHSidebarNav/GHRevealViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHSidebarViewController.m 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | #import "GHRevealViewController.h" 9 | #import 10 | 11 | 12 | #pragma mark - 13 | #pragma mark Constants 14 | const NSTimeInterval kGHRevealSidebarDefaultAnimationDuration = 0.25; 15 | const CGFloat kGHRevealSidebarWidth = 260.0f; 16 | const CGFloat kGHRevealSidebarFlickVelocity = 1000.0f; 17 | 18 | 19 | #pragma mark - 20 | #pragma mark Private Interface 21 | @interface GHRevealViewController () 22 | @property (nonatomic, readwrite, getter = isSidebarShowing) BOOL sidebarShowing; 23 | @property (nonatomic, readwrite, getter = isSearching) BOOL searching; 24 | @property (nonatomic, strong) UIView *searchView; 25 | - (void)hideSidebar; 26 | @end 27 | 28 | 29 | #pragma mark - 30 | #pragma mark Implementation 31 | @implementation GHRevealViewController { 32 | @private 33 | UIView *_sidebarView; 34 | UIView *_contentView; 35 | UITapGestureRecognizer *_tapRecog; 36 | } 37 | 38 | - (void)setSidebarViewController:(UIViewController *)svc { 39 | if (_sidebarViewController == nil) { 40 | svc.view.frame = _sidebarView.bounds; 41 | svc.view.autoresizingMask = UIViewAutoresizingFlexibleHeight; 42 | _sidebarViewController = svc; 43 | [self addChildViewController:_sidebarViewController]; 44 | [_sidebarView addSubview:_sidebarViewController.view]; 45 | [_sidebarViewController didMoveToParentViewController:self]; 46 | } else if (_sidebarViewController != svc) { 47 | svc.view.frame = _sidebarView.bounds; 48 | svc.view.autoresizingMask = UIViewAutoresizingFlexibleHeight; 49 | [_sidebarViewController willMoveToParentViewController:nil]; 50 | [self addChildViewController:svc]; 51 | self.view.userInteractionEnabled = NO; 52 | [self transitionFromViewController:_sidebarViewController 53 | toViewController:svc 54 | duration:0 55 | options:UIViewAnimationOptionTransitionNone 56 | animations:^{} 57 | completion:^(BOOL finished){ 58 | self.view.userInteractionEnabled = YES; 59 | [_sidebarViewController removeFromParentViewController]; 60 | [svc didMoveToParentViewController:self]; 61 | _sidebarViewController = svc; 62 | } 63 | ]; 64 | } 65 | } 66 | 67 | - (void)setContentViewController:(UIViewController *)cvc { 68 | if (_contentViewController == nil) { 69 | cvc.view.frame = _contentView.bounds; 70 | _contentViewController = cvc; 71 | [self addChildViewController:_contentViewController]; 72 | [_contentView addSubview:_contentViewController.view]; 73 | [_contentViewController didMoveToParentViewController:self]; 74 | } else if (_contentViewController != cvc) { 75 | cvc.view.frame = _contentView.bounds; 76 | [_contentViewController willMoveToParentViewController:nil]; 77 | [self addChildViewController:cvc]; 78 | self.view.userInteractionEnabled = NO; 79 | [self transitionFromViewController:_contentViewController 80 | toViewController:cvc 81 | duration:0 82 | options:UIViewAnimationOptionTransitionNone 83 | animations:^{} 84 | completion:^(BOOL finished){ 85 | self.view.userInteractionEnabled = YES; 86 | [_contentViewController removeFromParentViewController]; 87 | [cvc didMoveToParentViewController:self]; 88 | _contentViewController = cvc; 89 | } 90 | ]; 91 | } 92 | } 93 | 94 | #pragma mark Memory Management 95 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 96 | if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { 97 | self.sidebarShowing = NO; 98 | self.searching = NO; 99 | _tapRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideSidebar)]; 100 | _tapRecog.cancelsTouchesInView = YES; 101 | 102 | self.view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); 103 | 104 | _sidebarView = [[UIView alloc] initWithFrame:self.view.bounds]; 105 | _sidebarView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); 106 | _sidebarView.backgroundColor = [UIColor clearColor]; 107 | [self.view addSubview:_sidebarView]; 108 | 109 | _contentView = [[UIView alloc] initWithFrame:self.view.bounds]; 110 | _contentView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); 111 | _contentView.backgroundColor = [UIColor clearColor]; 112 | _contentView.layer.masksToBounds = NO; 113 | _contentView.layer.shadowColor = [UIColor blackColor].CGColor; 114 | _contentView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f); 115 | _contentView.layer.shadowOpacity = 1.0f; 116 | _contentView.layer.shadowRadius = 2.5f; 117 | _contentView.layer.shadowPath = [UIBezierPath bezierPathWithRect:_contentView.bounds].CGPath; 118 | [self.view addSubview:_contentView]; 119 | } 120 | return self; 121 | } 122 | 123 | #pragma mark UIViewController 124 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation { 125 | return (orientation == UIInterfaceOrientationPortraitUpsideDown) 126 | ? (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 127 | : YES; 128 | } 129 | 130 | #pragma mark Public Methods 131 | - (void)dragContentView:(UIPanGestureRecognizer *)panGesture { 132 | CGFloat translation = [panGesture translationInView:self.view].x; 133 | if (panGesture.state == UIGestureRecognizerStateChanged) { 134 | if (_sidebarShowing) { 135 | if (translation > 0.0f) { 136 | _contentView.frame = CGRectOffset(_contentView.bounds, kGHRevealSidebarWidth, 0.0f); 137 | self.sidebarShowing = YES; 138 | } else if (translation < -kGHRevealSidebarWidth) { 139 | _contentView.frame = _contentView.bounds; 140 | self.sidebarShowing = NO; 141 | } else { 142 | _contentView.frame = CGRectOffset(_contentView.bounds, (kGHRevealSidebarWidth + translation), 0.0f); 143 | } 144 | } else { 145 | if (translation < 0.0f) { 146 | _contentView.frame = _contentView.bounds; 147 | self.sidebarShowing = NO; 148 | } else if (translation > kGHRevealSidebarWidth) { 149 | _contentView.frame = CGRectOffset(_contentView.bounds, kGHRevealSidebarWidth, 0.0f); 150 | self.sidebarShowing = YES; 151 | } else { 152 | _contentView.frame = CGRectOffset(_contentView.bounds, translation, 0.0f); 153 | } 154 | } 155 | } else if (panGesture.state == UIGestureRecognizerStateEnded) { 156 | CGFloat velocity = [panGesture velocityInView:self.view].x; 157 | BOOL show = (fabs(velocity) > kGHRevealSidebarFlickVelocity) 158 | ? (velocity > 0) 159 | : (translation > (kGHRevealSidebarWidth / 2)); 160 | [self toggleSidebar:show duration:kGHRevealSidebarDefaultAnimationDuration]; 161 | 162 | } 163 | } 164 | 165 | - (void)toggleSidebar:(BOOL)show duration:(NSTimeInterval)duration { 166 | [self toggleSidebar:show duration:duration completion:^(BOOL finshed){}]; 167 | } 168 | 169 | - (void)toggleSidebar:(BOOL)show duration:(NSTimeInterval)duration completion:(void (^)(BOOL finsihed))completion { 170 | __weak GHRevealViewController *selfRef = self; 171 | void (^animations)(void) = ^{ 172 | if (show) { 173 | _contentView.frame = CGRectOffset(_contentView.bounds, kGHRevealSidebarWidth, 0.0f); 174 | [_contentView addGestureRecognizer:_tapRecog]; 175 | [selfRef.contentViewController.view setUserInteractionEnabled:NO]; 176 | } else { 177 | if (self.isSearching) { 178 | _sidebarView.frame = CGRectMake(0.0f, 0.0f, kGHRevealSidebarWidth, CGRectGetHeight(self.view.bounds)); 179 | } else { 180 | [_contentView removeGestureRecognizer:_tapRecog]; 181 | } 182 | _contentView.frame = _contentView.bounds; 183 | [selfRef.contentViewController.view setUserInteractionEnabled:YES]; 184 | } 185 | selfRef.sidebarShowing = show; 186 | }; 187 | if (duration > 0.0) { 188 | [UIView animateWithDuration:duration 189 | delay:0 190 | options:UIViewAnimationOptionCurveEaseInOut 191 | animations:animations 192 | completion:completion]; 193 | } else { 194 | animations(); 195 | completion(YES); 196 | } 197 | } 198 | 199 | - (void)toggleSearch:(BOOL)showSearch withSearchView:(UIView *)srchView duration:(NSTimeInterval)duration { 200 | [self toggleSearch:showSearch withSearchView:srchView duration:duration completion:^(BOOL finished){}]; 201 | } 202 | 203 | - (void)toggleSearch:(BOOL)showSearch withSearchView:(UIView *)srchView duration:(NSTimeInterval)duration completion:(void (^)(BOOL finsihed))completion { 204 | if (showSearch) { 205 | srchView.frame = self.view.bounds; 206 | } else { 207 | _sidebarView.alpha = 0.0f; 208 | _contentView.frame = CGRectOffset(self.view.bounds, CGRectGetWidth(self.view.bounds), 0.0f); 209 | [self.view addSubview:_contentView]; 210 | } 211 | void (^animations)(void) = ^{ 212 | if (showSearch) { 213 | _contentView.frame = CGRectOffset(_contentView.bounds, CGRectGetWidth(self.view.bounds), 0.0f); 214 | [_contentView removeGestureRecognizer:_tapRecog]; 215 | [_sidebarView removeFromSuperview]; 216 | self.searchView = srchView; 217 | [self.view insertSubview:self.searchView atIndex:0]; 218 | } else { 219 | _sidebarView.frame = CGRectMake(0.0f, 0.0f, kGHRevealSidebarWidth, CGRectGetHeight(self.view.bounds)); 220 | _sidebarView.alpha = 1.0f; 221 | [self.view insertSubview:_sidebarView atIndex:0]; 222 | self.searchView.frame = _sidebarView.frame; 223 | _contentView.frame = CGRectOffset(_contentView.bounds, kGHRevealSidebarWidth, 0.0f); 224 | } 225 | }; 226 | void (^fullCompletion)(BOOL) = ^(BOOL finished){ 227 | if (showSearch) { 228 | _contentView.frame = CGRectOffset(_contentView.bounds, CGRectGetHeight([UIScreen mainScreen].bounds), 0.0f); 229 | [_contentView removeFromSuperview]; 230 | } else { 231 | [_contentView addGestureRecognizer:_tapRecog]; 232 | [self.searchView removeFromSuperview]; 233 | self.searchView = nil; 234 | } 235 | self.sidebarShowing = YES; 236 | self.searching = showSearch; 237 | completion(finished); 238 | }; 239 | if (duration > 0.0) { 240 | [UIView animateWithDuration:duration 241 | delay:0 242 | options:UIViewAnimationOptionCurveEaseInOut 243 | animations:animations 244 | completion:fullCompletion]; 245 | } else { 246 | animations(); 247 | fullCompletion(YES); 248 | } 249 | } 250 | 251 | #pragma mark Private Methods 252 | - (void)hideSidebar { 253 | [self toggleSidebar:NO duration:kGHRevealSidebarDefaultAnimationDuration]; 254 | } 255 | 256 | @end 257 | -------------------------------------------------------------------------------- /GHSidebarNav/GHSidebarSearchViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHSidebarSearchViewController.h 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | #import "GHSidebarSearchViewControllerDelegate.h" 9 | @class GHRevealViewController; 10 | 11 | 12 | extern const NSTimeInterval kGHSidebarDefaultSearchDelay; 13 | 14 | @interface GHSidebarSearchViewController : UIViewController 15 | 16 | @property (nonatomic, readonly) UISearchBar *searchBar; 17 | @property (nonatomic, readonly) NSArray *entries; 18 | @property (weak, nonatomic) id searchDelegate; 19 | @property (nonatomic) NSTimeInterval searchDelay; 20 | 21 | - (id)initWithSidebarViewController:(GHRevealViewController *)sidebarVC; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /GHSidebarNav/GHSidebarSearchViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHSidebarSearchViewController.m 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 11/20/11. 6 | // 7 | 8 | #import "GHSidebarSearchViewController.h" 9 | #import "GHRevealViewController.h" 10 | 11 | 12 | #pragma mark - 13 | #pragma mark Constants 14 | const NSTimeInterval kGHSidebarDefaultSearchDelay = 0.8; 15 | 16 | 17 | #pragma mark - 18 | #pragma mark Private Interface 19 | @interface GHSidebarSearchViewController () 20 | @property (nonatomic, strong) UISearchDisplayController *searchDisplayController; 21 | @property (nonatomic, strong) NSMutableArray *mutableEntries; 22 | - (void)performSearch; 23 | @end 24 | 25 | 26 | #pragma mark - 27 | #pragma mark Implementation 28 | @implementation GHSidebarSearchViewController { 29 | @private 30 | GHRevealViewController *_sidebarVC; 31 | NSOperationQueue *_searchQueue; 32 | NSTimer *_timer; 33 | UIView *_searchBarSuperview; 34 | NSUInteger _searchBarSuperIndex; 35 | } 36 | 37 | #pragma mark Properties 38 | @synthesize searchDisplayController; 39 | 40 | - (UISearchBar *)searchBar { 41 | return searchDisplayController.searchBar; 42 | } 43 | 44 | - (NSArray *)entries { 45 | return _mutableEntries; 46 | } 47 | 48 | #pragma mark Memory Management 49 | - (id)initWithSidebarViewController:(GHRevealViewController *)sidebarVC { 50 | if (self = [super initWithNibName:nil bundle:nil]){ 51 | _sidebarVC = sidebarVC; 52 | _searchQueue = [[NSOperationQueue alloc] init]; 53 | _searchQueue.maxConcurrentOperationCount = 1; 54 | 55 | self.searchDelay = kGHSidebarDefaultSearchDelay; 56 | self.mutableEntries = [[NSMutableArray alloc] initWithCapacity:10]; 57 | 58 | self.searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:[[UISearchBar alloc] init] contentsController:self]; 59 | searchDisplayController.delegate = self; 60 | searchDisplayController.searchResultsDataSource = self; 61 | searchDisplayController.searchResultsDelegate = self; 62 | } 63 | return self; 64 | } 65 | 66 | - (void)dealloc { 67 | [_timer invalidate]; 68 | [_searchQueue cancelAllOperations]; 69 | } 70 | 71 | #pragma mark UIViewController 72 | - (void)viewDidLoad { 73 | [super viewDidLoad]; 74 | self.view.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth); 75 | } 76 | 77 | - (void)viewDidLayoutSubviews { 78 | if ([self respondsToSelector:@selector(topLayoutGuide)]) { 79 | CGRect viewBounds = self.view.frame; 80 | CGFloat topBarOffset = self.topLayoutGuide.length; 81 | self.view.frame = CGRectMake(viewBounds.origin.x, topBarOffset, 82 | viewBounds.size.width, viewBounds.size.height); 83 | } 84 | } 85 | 86 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation { 87 | return (orientation == UIInterfaceOrientationPortraitUpsideDown) 88 | ? (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 89 | : YES; 90 | } 91 | 92 | #pragma mark UITableViewDelegate 93 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 94 | if (_searchDelegate) { 95 | [_searchDelegate searchResult:_mutableEntries[indexPath.row] selectedAtIndexPath:indexPath]; 96 | } 97 | } 98 | 99 | #pragma mark UITableViewDataSource 100 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 101 | return _mutableEntries.count; 102 | } 103 | 104 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 105 | UITableViewCell *cell = nil; 106 | if (_searchDelegate) { 107 | id entry = _mutableEntries[indexPath.row]; 108 | cell = [_searchDelegate searchResultCellForEntry:entry atIndexPath:indexPath inTableView:tableView]; 109 | } 110 | return cell; 111 | } 112 | 113 | #pragma mark UISearchDisplayDelegate 114 | - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller { 115 | _searchBarSuperview = self.searchBar.superview; 116 | _searchBarSuperIndex = [_searchBarSuperview.subviews indexOfObject:self.searchBar]; 117 | 118 | [self.searchBar removeFromSuperview]; 119 | [self.view addSubview:self.searchBar]; 120 | [self.searchBar sizeToFit]; 121 | [self.searchBar setShowsCancelButton:YES animated:YES]; 122 | 123 | [_sidebarVC toggleSearch:YES withSearchView:self.view duration:kGHRevealSidebarDefaultAnimationDuration]; 124 | [self.searchBar becomeFirstResponder]; 125 | } 126 | 127 | - (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView { 128 | tableView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); 129 | tableView.backgroundColor = [UIColor clearColor]; 130 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 131 | } 132 | 133 | - (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller { 134 | controller.searchResultsTableView.alpha = 0.0; 135 | [_sidebarVC toggleSearch:NO withSearchView:self.view duration:kGHRevealSidebarDefaultAnimationDuration completion:^(BOOL finished){ 136 | [self.searchBar resignFirstResponder]; 137 | [self.searchBar removeFromSuperview]; 138 | self.searchBar.showsCancelButton = NO; 139 | [_searchBarSuperview insertSubview:self.searchBar atIndex:_searchBarSuperIndex]; 140 | _searchBarSuperview = nil; 141 | }]; 142 | } 143 | 144 | - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { 145 | [_timer invalidate]; 146 | [_searchQueue cancelAllOperations]; 147 | _timer = [NSTimer scheduledTimerWithTimeInterval:_searchDelay target:self selector:@selector(performSearch) userInfo:nil repeats:NO]; 148 | return NO; 149 | } 150 | 151 | - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption { 152 | [_timer invalidate]; 153 | [_searchQueue cancelAllOperations]; 154 | _timer = [NSTimer scheduledTimerWithTimeInterval:_searchDelay target:self selector:@selector(performSearch) userInfo:nil repeats:NO]; 155 | return NO; 156 | } 157 | 158 | #pragma mark Private Methods 159 | - (void)performSearch { 160 | NSString *text = self.searchBar.text; 161 | NSString *scope = (self.searchBar.showsScopeBar) 162 | ? self.searchBar.scopeButtonTitles[self.searchBar.selectedScopeButtonIndex] 163 | : nil; 164 | if ([@"" isEqualToString:text]) { 165 | [_mutableEntries removeAllObjects]; 166 | [searchDisplayController.searchResultsTableView reloadData]; 167 | } else { 168 | if (_searchDelegate) { 169 | __block GHSidebarSearchViewController *selfRef = self; 170 | __block NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 171 | [selfRef.searchDelegate searchResultsForText:text withScope:scope callback:^(NSArray *results){ 172 | if (![operation isCancelled]) { 173 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 174 | if (![operation isCancelled]) { 175 | [selfRef.mutableEntries removeAllObjects]; 176 | [selfRef.mutableEntries addObjectsFromArray:results]; 177 | [selfRef.searchDisplayController.searchResultsTableView reloadData]; 178 | } 179 | }]; 180 | } 181 | }]; 182 | }]; 183 | [_searchQueue addOperation:operation]; 184 | } 185 | } 186 | } 187 | 188 | @end 189 | -------------------------------------------------------------------------------- /GHSidebarNav/GHSidebarSearchViewControllerDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHSidebarSearchViewControllerDelegate.h 3 | // GHSidebarNav 4 | // 5 | // Created by Greg Haines on 1/7/12. 6 | // 7 | 8 | 9 | typedef void (^SearchResultsBlock)(NSArray *); 10 | 11 | @protocol GHSidebarSearchViewControllerDelegate 12 | @required 13 | - (void)searchResultsForText:(NSString *)text withScope:(NSString *)scope callback:(SearchResultsBlock)callback; 14 | - (void)searchResult:(id)result selectedAtIndexPath:(NSIndexPath *)indexPath; 15 | - (UITableViewCell *)searchResultCellForEntry:(id)entry atIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)tableView; 16 | @end 17 | -------------------------------------------------------------------------------- /GHSidebarNav/Images/searchBarBG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gresrun/GHSidebarNav/7133823c74238d6b65c412997ec912b2d1716fea/GHSidebarNav/Images/searchBarBG.png -------------------------------------------------------------------------------- /GHSidebarNav/Images/searchBarIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gresrun/GHSidebarNav/7133823c74238d6b65c412997ec912b2d1716fea/GHSidebarNav/Images/searchBarIcon.png -------------------------------------------------------------------------------- /GHSidebarNav/Images/searchBarIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gresrun/GHSidebarNav/7133823c74238d6b65c412997ec912b2d1716fea/GHSidebarNav/Images/searchBarIcon@2x.png -------------------------------------------------------------------------------- /GHSidebarNav/Images/searchTextBG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gresrun/GHSidebarNav/7133823c74238d6b65c412997ec912b2d1716fea/GHSidebarNav/Images/searchTextBG.png -------------------------------------------------------------------------------- /GHSidebarNav/Images/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gresrun/GHSidebarNav/7133823c74238d6b65c412997ec912b2d1716fea/GHSidebarNav/Images/user.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | 204 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GHSideBarNav 2 | ============ 3 | 4 | A clone of the new Facebook iOS UI paradigm; a sidebar navigation table that is revealed by sliding the main content panel to the right. The search goes full-screen and everything supports the standard orientations. 5 | 6 | This project uses the Container View Controller methods introduced in iOS 5.0 so, it won't work on any version prior. 7 | This project uses ARC so, you'll need Mac OS 10.7+ (Lion) and Xcode 4.2.1+ to build it. 8 | 9 | [![](http://gresrun.github.com/GHSidebarNav/sidebarScreenshot.png)](http://gresrun.github.com/GHSidebarNav/sidebarScreenshot.png) 10 | [![](http://gresrun.github.com/GHSidebarNav/searchScreenshot.png)](http://gresrun.github.com/GHSidebarNav/searchScreenshot.png) 11 | 12 | *** 13 | How Do I Use It? 14 | ---------------- 15 | 16 | 1. Copy the core components (GHRevealViewController, GHSidebarSearchViewController and GHSidebarSearchViewControllerDelegate) into your project. 17 | 1. Use GHAppDelegate as a template to integrate GHRevealViewController into your main window in your project's AppDelegate, sending your own headers, controllers and cellInfos. 18 | 1. Implement GHSidebarSearchViewControllerDelegate to find your search results (call a web service, etc.) and do something with the selected search result. 19 | 1. Modify the colors and appearance to match your color scheme. 20 | 21 | *** 22 | License 23 | ------- 24 | Copyright 2011 Greg Haines 25 | 26 | Licensed under the Apache License, Version 2.0 (the "License"); 27 | you may not use this file except in compliance with the License. 28 | You may obtain a copy of the License at 29 | 30 | 31 | 32 | Unless required by applicable law or agreed to in writing, software 33 | distributed under the License is distributed on an "AS IS" BASIS, 34 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 | See the License for the specific language governing permissions and 36 | limitations under the License. 37 | --------------------------------------------------------------------------------