My favorite sidebar controller: https://github.com/mutualmobile/MMDrawerController
MMDrawerController is very customizable and does everything you mentioned:
- left and right controller support
- preset side controllers
- gesture drag and drop
If you are using a storyboard, you can use this extension to support the storyboard: https://github.com/TomSwift/MMDrawerController-Storyboard
EDIT:
Another option would be to use a UIPageViewController with a UIPageViewControllerTransitionStyleScroll transition UIPageViewControllerTransitionStyleScroll : https://developer.apple.com/library/ios/documentation/uikit/reference/UIPageViewControllerClassReferenceClassRef/UIPageViewControllerClassReference.html
This will lead to the “pulling” behavior in the controllers on the side and “expanding” them.
EDIT 2: example for request
The only real complicating requirement you have is that the same view controller is used for both the left and the right. This means that we must keep track of where the view controller is presented so that we can properly manage our data source. Without this requirement, we could simply return our data source with an array and get the next / previous of this.
First of all, storyboard. There are three view controllers in the storyboard: 1) UIPageViewController , which I have classified as TSPageViewController . Remember to set the transition style property on the scroll page of the controller. 2) a center controller; and 3) a side controller. For center and side, I set the storyboard identifier of each of them to “center” and “side”, respectively. For this sample, both the central and side controllers have simple vanilla UIViewControllers , and I set their backgroundColor view to tell them apart.

Secondly, the pageview controller:
.h
@interface TSPageViewController : UIPageViewController @end
.m
@interface TSPageViewController () <UIPageViewControllerDataSource> @end @implementation TSPageViewController { UIViewController* _side; UIViewController* _center; } - (void) viewDidLoad { [super viewDidLoad]; self.dataSource = self; _side = [self.storyboard instantiateViewControllerWithIdentifier: @"side"]; _center = [self.storyboard instantiateViewControllerWithIdentifier: @"center"]; [self setViewControllers: @[_center] direction: UIPageViewControllerNavigationDirectionForward animated: NO completion: nil]; } - (UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { if ( viewController == _center ) { _side.title = @"right"; return _side; } if ( viewController == _side && [_side.title isEqualToString: @"left"] ) { return _center; } return nil; } - (UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { if ( viewController == _center ) { _side.title = @"left"; return _side; } if ( viewController == _side && [_side.title isEqualToString: @"right"] ) { return _center; } return nil; } @end
Again, the only thing that is especially important is to keep track of whether the side controller is currently “left” or “right.” This implementation has a problem in that it relies on the behavior of the UIPageViewController, rather than on the "page forward" and on the cache controllers (if this happened, our logic would be confused). Therefore, you can think of a more reliable mechanism for tracking the side on which the view controller is currently turned on. To do this, you will most likely have to enter your own gesture recognizer and use the data to track left / right movement.
If you can give up your requirement to use the same view controller for left and right, then you can have separate left / right / center controllers stored in the array and return next / prev controllers based on what you see in the array. Much easier and more reliable!