MGSplitViewController is an open source replacement for UISplitViewController, with various useful enhancements.
Here’s a demonstration video hosted on YouTube. It’s better if you watch it in full HD.
Donations
I wrote MGSplitViewController for my own use, but I’m making it available (as usual) for the benefit of the iOS developer community, because I care about this community and about the platform.
If you make use of MGSplitViewController, a Paypal donation (or something from my Amazon.co.uk Wishlist) would be very much appreciated. Appropriate links can be found here.
It’s taken a fair bit of work to refine the code to a flexible, reusable state, and I hope you’ll find it useful in your own projects. It’s my goal that it should save you many hours or days of work.
Features
Please note that, since split-views are commonly used for “Master-Detail” interfaces, I call the first sub-view the “master” and the second sub-view the “detail”.
- By default, MGSplitViewController mimics the appearance and (complete) behaviour of UISplitViewController, including its delegate API. It accepts two UIViewControllers (or subclasses thereof).
- Allows toggling the visibility of the master view in either interface-orientation; i.e. you can have master-detail or detail-only in either landscape and/or portrait orientations (independently, and/or interactively).
- Allows choosing whether the split orientation is vertical (i.e. left/right, like UISplitViewController), or horizontal (master above, and detail below). You can toggle between modes interactively, with animation.
- Allows choosing whether the master view is before (above, or to left of) the detail view, or after it (below, or to the right).
- Allows you to choose (and change) the position of the split, i.e. the relative sizes of the master and detail views.
- Allows you to enable dragging of the split/divider between the master and detail views, with optional constraining via a delegate method.
- Allows you to choose the width of the split between the master and detail views.
- Preset “divider styles“: one for non-draggable UISplitViewController-like dividers, and one for draggable, thicker style with a grip-strip.
- Allows you to substitute your own divider-view (an MGSplitDividerView subclass), used to draw the split between the master and detail views.
Getting the Code
MGSplitViewController is hosted on github, for ease of sharing; you can get the code here.
If you find it useful, it’d be much appreciated if you leave a comment to that effect here, and (ahem) note the Donations section above. Relax, that’s the last time I’ll mention it.
How to use
The “MGSplitViewController.h” header file (and the sample project) should be self-explanatory. It’s recommended that you use the project as a reference.
Interface Builder support
At time of writing, MGSplitViewController cannot be quite as elegantly visually configured like UISplitViewController using Interface Builder.
You can, however, (and it is recommended that you do) create an instance of it in a xib, and connect the masterViewController and detailViewController outlets to the required view-controllers.
License and Warranty
The license for the code is included with the project; it’s basically a BSD license with attribution.
You’re welcome to use it in commercial, closed-source, open source, free or any other kind of software, as long as you credit me appropriately. If you require a different open source license, please contact me (details below). If you need a license without the attribution requirement, a fee will be payable.
The MGSplitViewController code comes with no warranty of any kind. I hope it’ll be useful to you (it certainly is to me), but I make no guarantees regarding its functionality or otherwise.
Support / Contact / Bugs / Features
I can’t answer any questions about how to use the code, but I always welcome emails telling me that you’re using it, or just saying thanks.
If you create an app which uses the code, I’d also love to hear about it. You can find my contact details here.
Likewise, if you want to submit a feature request or bug report, feel free to get in touch. Better yet, fork the code and implement the feature/fix yourself, then submit a pull request.
You can keep up to date with what I’m working on by following me (@mattgemmell) on Twitter, and you can see my apps (or enquire about hiring me for your projects) at my business site, Instinctive Code.
Enjoy the code!
[...] This post was mentioned on Twitter by WPstudios, Matt Legend Gemmell, Zettt, Luke Redpath, Bagelturf and others. Bagelturf said: RT @mattgemmell MGSplitViewController for iPad: http://mattgemmell.com/mgsplitviewcontroller-for-ipad [...]
Looks great! I might be wanting something like this in a future project.
Looking forward to seeing the app that required this too.
[...] ever-resourceful Matt Gemmell developed the UISplitViewController Apple should have made: MGSplitViewController can display the split view in landscape and portrait, has a vertical and a horizontal layout, and [...]
Impressive work! IMHO much needed improvement to the stock UISplitViewController.
Thank for you making this source available to others. I am also grateful for your contribution of Twitter Objective-C library.
’tis a thing of beauty
[...] MGSplitViewController for iPad [...]
Looks pretty awesome !
Might use it on a future project, I’ll let you know.
Got a tiny bug in the demo while playing with it : http://emberapp.com/etiennesegonzac/images/mgsplitviewcontroller-demo-bug
The UILabel in the detail view goes over the divider.
Looks like the detail view bounds don’t account for the divider width.
Cheers !
Wow, this is exactly what I need for a project I just started. Will definitely be running this through it paces.
Hi,
I downloaded the code, but when I try to build it it gives me a bunch of:
/MGSplitViewController.m:1019:13: error: synthesized property ‘showsMasterInPortrait’ must either be named the same as a compatible ivar or must explicitly name an ivar
What am I doing wrong?
Thanks
Michele,
If I did not know any better, I would say that you are trying to build for the old Obj-C runtime.
Other than that, do another git clone and try again. I just tried it with Xcode 3.2.3 on 10.6.4 and it built just fine out of the box.
Having to roll my own version of split view to do what I really wanted was a semi-blocker for me. Wow. Glad I heard of this and if it works for me I’ll be paying you for the code
Very nice looking split view controller. I’ll download it and check it out.
On another note, can you tell me what you used to make the video of the iPad screen for the demo?
Thanks,
Tony
It’s just a video of the iPad Simulator on Mac OS X. I captured it with ScreenFlow.
Seriously amazing. This saved me hours and hours of work, and I can’t thank you enough. The split view controller is fairly limited; this one trumps it by miles!! Hope someday that I’ll be able to make such meaningful contributions to the iOS community.
Amazing work and contribution to the iOS community! Thank you!
Doesn’t Apple explicitly state that you can only have one UIViewController on the screen at once, unless you use one of their container VCs? There are all sorts of issues that arise with UIWindow delegate behavior, proper dispatch of notifications, implicit linkages between tab bar controllers and subsidiary view controllers, and other private, internal, undocumented behavior.
Over the years, I’ve run into all sorts of edge cases and issues due to internal APIs that tie UIWindow, UIView, and UIViewController instances together. Sometimes things mostly work, and then stop working properly in later releases.
From the View Controller Programming Guide:
Each custom view controller object you create is responsible for managing exactly one screen’s worth of content. The one-to-one correspondence between a view controller and a screen is a very important consideration in the design of your application. You should not use multiple custom view controllers to manage different portions of the same screen. Similarly, you should not use a single custom view controller object to manage multiple screens worth of content.
Note: If you want to divide a single screen into multiple areas and manage each one separately, use generic controller objects (custom objects descending from NSObject) instead of view controller objects to manage each subsection of the screen. Then use a single view controller object to manage the generic controller objects. The view controller coordinates the overall screen interactions but forwards messages as needed to the generic controller objects it manages.
I have read that doc also and I get the impression that it’s left over from iPhone-only days. On the iPad, it makes much more sense to use a controller for every view (of which there are many) and Apple’s own code often demands multiple active concurrent view controllers, as in popovers and this splitview example.
Curtis: My interpretation is similar to Stephen’s. In the event that the architecture of MGSVC causes approval problems, it’ll be a very simple matter indeed to modify it to accept two arbitrary/generic controller objects which provide a view, rather than UIViewControllers.
I don’t think it’s a matter of style — it’s really not a supported configuration, and leads to unexpected issues and undefined behavior. To quote a post to the iPhone dev list on your implementation:
Nice link. Note that your detail and master view controllers won’t be completely set-up (eg.: parentViewController will return nil); which can – in rare occasions – cause trouble when you display modal view controllers (even if you don’t rely on the values of parentViewController and the like, the OS does).
There’s far too much black magic that connects view controllers, views, and windows together — it’s a really badly designed API, and trying to manage your own containers without explicit API support is invariably troublesome.
You’re almost better off creating your own fully independent VC replacement than trying to shoehorn UIViewController into place. Maybe Apple will fix the VC API in future, but they didn’t for iOS4, and I wouldn’t want to rely on this in the meantime (and then have it break in a funny new way on a new OS while I scramble to “modify it to accept two arbitrary/generic controller objects which provide a view” (which won’t really solve the problem if you’re relying on the ability to push arbitrary VCs into that split view).
“screen’s worth of content”
If you watch the Stanford iPhone courses you will hear them refer to this as well. They are talking about the iPhone.
I am trying to create a 2 master pane split view. The app I am working on has 2 levels of hierarchy before showing the details.
I wanted to use a splitview within another splitview. But I am getting into a lot of trouble with rotation. In your code the frame sizes are based on the iPad resolution. If the splitview is not actually the size of the iPad (like my inner splitview) the frame sizes don’t work. I have been trying to change the splitView size to be based on it’s frame instead of the screen.
Any pointers where to look? I have be stuck of a couple hours.
i managed to hack it out…
1. the child split view needed a pointer to the parent to see if the master pane of the parent is showing.
2. If the master pane of parent is showing, subtract the width of the master pane from the screen width.
3. In WillRotate, layout the view before calling willrotate of the master/detail view
[...] You can find the original writeup on it here: MGSplitViewController For iPad [...]
anyone know how to make default RootViewController (list table) displayed on the right side ? please advise
“Sereal”,
Did you even look at the project/code before posting your question? The demo app makes it very clear how to do that. Do your research.
sorry to post Matt. finaly i understand your code after hours of reading it. i want to say thanks for making this study beautiful. thank you
I’m going crazy! I can’t remove the Buttons or the Toolbar from the DetailViewController, I just get crashes…
Can anybody tell me if it’s enough to remove ir from the DetailViewController.h and DetailViewController.m?
Do I have to change something in MGSplitDividerView? wich lines? Any Example?
By the way I’ve got to say THANK YOU MATT. I’m a newby in iOS and your controller makes exactly what I wanted to do in my first iPad APP, and I was giving up as I tought it was imposible with Apple’s controllers and then I came across with your Controller. I’ve already told my boss that if we get it we’ve got to buy something of your Amazon’s Wishlist.
Sorry for disturbing Matt I’ve just found the solution (it’s just my first month in iOS and Objective-C programming, I’m moving from PHP/Ajax/ActionScript), do you know what it’s like when you spend half day (or more) trying and trying and when you wake up the next they you find the solution in 2 minutes? It has happened to me, the second thing I’ve done just after leaving my previous comment it’s been to try and find the solution in 2 minutes.
By the way, I’sure we gonna buy you something.
Hi Matt,
this looks fantasic. I was just looking into how to get the master view to stay visible in portrait view. It seems Apple have a hidden API (rejection) for that.
In the middle of building a universal app at the moment. I’ll download and try this evening.
If I end up using it, I’ll push something through the paypal vortex for you.
Cheers.
Hi,
Very good control I must say. We are trying to fit it into an existing in development app, specifically so we can set the master width (why Apple didn’t think it was a good idea to allow you to do this I don’t know; especially when we just want the details view to be the same width in all orientations!).
Anyhow it seems to work except the details view is always blank (we see the main window background).
We load the specific detail nib and insert the contents into a scroll view that is in the details nib.
Even without doing that and just trying to show the details nib with a label with “text here” doesn’t work.
If you have any ideas on what the issue may be (superview not set, bad bindings between the nib and the code?) that would be grand!
Thanks