mattgemmell / mgsplitviewcontroller Goto Github PK
View Code? Open in Web Editor NEWA flexible, advanced split-view controller for iPad developers.
Home Page: http://mattgemmell.com/
A flexible, advanced split-view controller for iPad developers.
Home Page: http://mattgemmell.com/
Hi,
this is not an issue... :)
but I can't figure out how to change the detailviewController.
From my masterview controller, I would like to change the detailViewController regarding the row pressed?
Any idea?
Hi,
this is not an issue... :)
but I can't figure out how to change the detailviewController.
From my masterview controller, I would like to change the detailViewController regarding the row pressed?
Any idea?
please give me small example or code
If for example the Master is a UINavigationController and you want to display the toolbar, it is just displayed as a black rectangle. There is no gradient. You cannot change the color of the toolbar. However, the toolbar items are displayed correctly.
app crashes when I add in the storyboard with "Could not load NIB in bundle" message
the resolve is to call [self setup]; in "viewDidLoad" method except "initWithCoder".
When using the methods setMasterViewController or setDetailViewController the view of the replaced viewcontroller is not removed from the view hierarchy. This leads to crashes as its viewController gets released and cannot received remaining delegate calls (e.g. UITableViewDataSource methods).
The setViewControllers methods correctly removes the old viewControllers' views before setting new ones.
calling
[[[self.splitViewController detailViewController] view] removeFromSuperview];
before setting the new detailViewController fixes this issue. I will do my best to submit a patch.
I can dismiss the modal view when cancel button is clicked. The problem may cause by the MFMailComposeViewController delegate does not correct. But I don't know how to fix it.
Thanks for helping me
Tung Do
I am trying to modify the background color of the navigation bar. The problem I am running into is that the color change only occurs up to where a UISplitViewController would end. The remaining section of the navigation bar os the default color. Here is how I am changing the color:
// the darker tint
float rd = 157.00/255.00;
float gr = 140.00/255.00;
float bl = 114.00/255.00;
// this creates the gradiant
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.navigationController.navigationBar.bounds;
gradient.colors = [NSArray arrayWithObjects: (id)[[UIColor whiteColor] CGColor], (id)[[UIColor colorWithRed:rd green:gr blue:bl alpha:1] CGColor], nil ];
[self.navigationController.navigationBar.layer insertSublayer:gradient atIndex:0];
I don't know how many attempts I have made but I cannot figure out how to solve this issue.
I have a button on my "detailsViewController" which is supposed to toggle the master view. It works just fine but when issued in landscape.
The first touch is fine, the masterview shrinks and leaves all the space for the detailsviewcontroller. When I tap it again, the application crashes.
The error I got is a EXC_BAD_ACCESS error on the workaround for the disarray bug (this line comes from iridia's fork but it happens the same also on Matt's)
[_hiddenPopoverController presentPopoverFromRect:CGRectZero inView:[UIApplication sharedApplication].keyWindow permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
I tried many forks but everyone seem to suffer of the same problem. I don't know what to try, I don't know what to change.
In portrait it works just fine.
Oh, another attempt I made was with Iridia's fork ( https://github.com/iridia/MGSplitViewController ) which gives a different problem: the popover shows up and is never dismissed. The application freezes but no crash there.
setViewControllers: iterates over _viewControllers and assumes that each item is a UIViewController (and accesses the view property). However, it is possible for an item in _viewControllers to be [NSNull null], so there needs to be a check for
if ([controller isKindOfClass:[UIViewController class]])
inside the for loop.
In iOS 6, the master view seems can't layout correctly. When I rotate the iPad from landscape to portrait then back to landscape, the UINavigationController will screw up, the navigation bar has lost the color, the size of the navigation isn't correct and the content view of the UINavigationController has offset.
Hi,
I have a UINavigationController as my RootViewController and there I have a UISearchBar with scope bar at the bottom of the view. The problem is in the landscape, when I click on the search field first time, everything is ok, but then when I cancel searching and click on it again, the scope bar disappears but the height of the search bar stays big and the field move to the center of the bar. When I open that view from popover everything is alright. Had anybody that?
I have a toggle button the animated the masterview between split position 250 and 0. It correctly animates, except as we are animating to 0.0 the TableView which is in the NavigationController in the masterview disappears immediately, so while the animation is running there is not table view visible while the masterview is still visible.
When I open a modal view with regard to the splitviewcontroller in portrait, then rotate to landscape and then dismiss modal view the app aborts and terminates. If I open and close the modal view in portrait or open and close the modal view in landscape not matter how many times I have rotated the view it works fine. But if open in Portrait and close in Landscape it aborts in the method- (void)reconfigureForMasterInPopover:(BOOL)inPopover when dealing with _hiddenPopover ?
It works if the modal view is opened in any style other than the default, in both the following styles it function correctly.
navController.modalPresentationStyle = UIModalPresentationFormSheet;
navController.modalPresentationStyle = UIModalPresentationPageSheet;
So, if default style in portrait (open) then rotate to landscape (close) it aborts.
I just opted to useUIModalPresentationPageSheet, but would like to have the flexibility to you the other default style also.
Thanks if anyone has any suggestions
The scenario: An MGSplitViewController subclass is the root controller of a UINavigationController.
The master view contains a navigation controller as is typical.
In this scenario. Then the view is initially displayed, the nav bar within the master view is drawn too thick, approx. 10 pixels too much. If the physical orientation of the device is changed, it is redrawn properly.
This implies that there is still some communication lacking from MGSplitViewController to the contained nav controller.
I think layoutSubviews in MGSplitViewController should only be called when self.isViewLoaded == YES. The problem is that layoutSubViews causes a load view for the root and details view controller as well and this may be too soon in the lifecycle, e.g. before the nib is fully loaded causing viewDidLoad to be called twice for those view controllers.
Also setup should not instantiate the MGSplitDividerView, this code should be moved to viewDidLoad (and should be deallocated in viewDidUnload).
I have recently modified MGSplitViewController as per my requirement and put the DetailViewController in MainWindows.xib in a navigationcontroller and showing it and it is working properly
// In MGSplitViewController.m do following changes
Now whenever i open the application in portrait mode, and try to show my custom view inside DetailviewController, the view is creating 20 px below navigation bar i.e. a little space (20 px ) is created below DetailViewController navigation bar then my view is getting displayed.
I have also changes as : https://github.com/mattgemmell/MGSplitViewController/pull/23/files
but still i am getting the issue , any body have find some solution to this .
Really nice control but a small problem:
If the app starts with landscape mode, after presenting a modal view and dismissing it (by using [self dismissModalViewControllerAnimated:YES]), the SplitView control just lost it's orientation.
I'm trying to figure out what's happening there.
I have add a uibarbutton item on detail View controlller & on selection of which i am trying to show a new view controller on Full screen mode But it is not working(Working in portrait mode but if i rotate it to Landscape mode it is not working.
-(IBAction)openPreviewScreen:(id)sender
{
NewViewController *newViewControllerObj=[[[NewViewController alloc] initWithNibName:@"NewViewController" bundle:nil] autorelease];
detailViewNavController = [[UINavigationController alloc] initWithRootViewController: newViewControllerObj];
detailViewNavController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
detailViewNavController.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentModalViewController:detailViewNavController animated:YES];
}
I set the default splitPosition to 250.00 But the NavController that I add to the masterview is not reflecting that width. It is much bigger, so the Header and TableView in the NavController is too wide and therefore doesn't display completely. It gets cut off at 250.00. But if I rotate, then the Nav view and tableview in the master update to the correct width.
My hierarchy consists of a UINavigationController which contains the MGSplitViewController and then inside the MGSplitViewController I have another UINavigationController in the masterView and a UIViewController in the detailView. Then inside the second UINavigationController I have a series of UITableViews.
Whenever I display the first UITableView, whenever I'm in landscape, the UITableView is 44px too tall (the height of a navigation bar). If I change orientations and change back, the view renders correctly.
What I have found out, is that [MGSplitViewController splitViewSizeForOrientation:] returns the correct size every time, but if print out the actual height of the UITableView after it loads (or changes orientation) the height is incorrect by 44px on load. On load the UITableView is 748px tall but after an orientation change it is 704px tall for landscape.
I've tried loading the second UINavigationController on its own and I've tried loading the first UITableView without the UINavigationController, and I've tried just loading the UITableView on its own. As soon as I remove MGSplitViewController from the hierarchy everything renders correctly.
So far my workaround has been to just keep track of the first time [MGSplitViewController layoutSubviewsForInterfaceOrientation:withAnimation:] and subtract the height of the navigation bar from the masterView, if it's in landscape orientation, otherwise calculate the dimensions normally.
I'm seeing cases where whenever an instance of MGSplitViewController is presented, the MGSplitViewController instance's -viewWillAppear:animated method is called.
Within this method, there is logic that will call -viewWlilAppear:animated on both the masterViewController and the detailViewController, even though they will have already been sent this message as being children of the MGSplitViewController. The code as it stands now causes the child view controllers' -viewWillAppear:animated to be called twice.
This can be an issue if you're expecting -viewWillAppear:animated to be called once per event for the view controllers inside either master or detail.
In a fairly complex app using UISplitViewController I replaced it with MGSplitViewController and had a crash on startup; I could solve the crash by applying this change to the class:
http://gist.github.com/503462
(I must say that the class worked perfectly well just by changing the class names from UI to MG. Amazing work.)
I'm trying to use a full screen modal view, however I'm getting really strange behavior when trying to present it from Landscape mode.
Presenting a modal view from Portrait mode seems to work OK, but in Landscape the whole screen is covered completely in white.
Also another strange issue is after the modal view has been presented when the iPad is rotated the modal view disappears suddenly and shows the underlying MGSplitView.
When compiling a universal binary for iPhone and iPad a run-time link error occurs when running the app on the phone.
In MGSplitViewController.m the line:
_hiddenPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.masterViewController];
Should be:
_hiddenPopoverController = [[NSClassFromString(@"UIPopoverController") alloc] initWithContentViewController:self.masterViewController];
To allow running on phones.
I am using a split view in landscape with the master permanently hidden. if I try to setDetailViewController before I have ever clicked the master button, the code seems to execute and the detailViewController is the correct VC, but the layout does not change and the displayed view is the original one.
My workaround right now is, just prior to the manual setting of the detailViewController I show and instantly hide the popover, then it works,
Sorry I can't be more help in terms of supplying a patch. The fact that the detailViewController is correctly set, but just not redisplaying has totally thrown me for a loop.
I am using MGSplitViewController with properties:
self.splitViewController.showsMasterInPortrait = YES;
self.splitViewController.splitPosition = 300;
I have a UINavigationController set to the masterViewController property, and upon rotating from lanscape to portriate, the navigation items are squished. I get around this at the moment with the following code within my master view controller:
It will only work when added as a subview of the main application window. If you add it as a subview of another view (even if the view is fullscreen), things start falling apart.
Note: tried the same with UISplitViewController and nothing happens (so it is nothing about my code).
When you present a modal view controller, if you change orientation while in the modal, the whole MGSplitViewController loose it's orientation
I am currently integrating MGSplitViewController in one of my application and its working properly.
But i want to modify the way it is displaying currently in portrait mode.So i want in portrait mode whenever application open it should display both master as well as detail view controller.So on pressing the navigation bar button it will again hide and show the left root view controller.
So i have changed the code to
(BOOL)shouldShowMasterForInterfaceOrientation:(UIInterfaceOrientation)theOrientation
{
// Returns YES if master view should be shown directly embedded in the splitview, instead of hidden in a popover.
//return ((UIInterfaceOrientationIsLandscape(theOrientation)) ? _showsMasterInLandscape : _showsMasterInPortrait);
return YES;
}
Now both portrait and landscape mode is showing both root and detail view controller as i wants but the problem is navigation bar button is not working to hide & show left root view controller.
Any body have done this?
I like you implementation as it is very useful and something I was about to build myself. But I find it a bit complicated, that one needs to get the relevant classes out of the sample project. A better solution would be to create your MGSVC framework as a static lib that can be included in some easy steps. Your sample project could include this project aswell.
Three20 did a great job splitting the framework from the sample project those days.
Just my 2ct.
I don't expect you can do anything about this but I thought I'd let you know of a way that MGSVC behaves differently from UISVC. If you have a full screen modal presented and receive a level 2 memory warning, UISVC will call viewDidUnload and clobber all of the views. Then when the modal is dismissed it rebuilds the controllers from the XIB. Anything not in the XIB has to be recreated in code. UISVC only does this on level 2 which is not even something we can access with public methods.
I found this behavior annoying when I first discovered it but came to appreciate it as it happens in my app when the user plays YouTube videos in UIWebViews that I present modally. With MGSVC the YouTube playback is less reliable and I'm trying to figure out a solution now.
We're using a UINavigationController to display a MGSplitViewController. When the splitview controller is animated in you can see the masterview when is shouldn't be displayed, in our case in portrait mode.
I found that the navBar height was not being subtracted from the height of the master view, affecting a custom tabbar. Added the following code to make that work:
- (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation
{
// Other code
// Account for status bar, which always subtracts from the height (since it's always at the top of the screen).
height -= statusBarHeight;
// new code
if (!self.navigationController.navigationBarHidden) {
height -= self.navigationController.navigationBar.frame.size.height;
}
// end new code
return CGSizeMake(width, height);
}}
Step to reproduce:
I'm currently working on fixing the issue but I'm not clear what is causing it
i'm trying to change the detail view with setDetailViewController() method, but nothing was working.
I play around with different options, i was able to use setViewControllers() to reload both master and detail views.
After i study the code a little more, i found out that in setViewControllers(), it remove all the views from the superview, before doing anything else.
for (UIViewController *controller in _viewControllers) {
if ([controller isKindOfClass:[UIViewController class]]) {
[controller.view removeFromSuperview];
}
}
So, i added the same code in the setDetailViewController(), and it seem to work perfectly.
if ([_viewControllers objectAtIndex:1] == detail) {
changed = NO;
} else {
if ([[_viewControllers objectAtIndex:1] isKindOfClass:[UIViewController class]]) {
[[[_viewControllers objectAtIndex:1] view] removeFromSuperview];
}
[_viewControllers replaceObjectAtIndex:1 withObject:detail];
}
Is this a bug in the code? or is there an easier way to replace the detail view without touching the master view?
result: viewWillAppear called on master
result: viewWillAppear not called on master
Master is never removed from the superView if the popover isn't invoked. It seems the correct behavior would be to remove it post animation though it wouldn't surprise me if there end up being timing issues with full 180 rotations or immediately opening the popover after rotation.
I found a bug when playing a mpmovieplayerviewcontroller inside a full screen modal.
Line 578 of mgsplitviewcontroller.m reads:
[_hiddenPopoverController presentPopoverFromRect:CGRectZero inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
but this causes a crash if self.view is not attached to a window.
So I added
if (self.view.window != nil)
before that line and that worked.
If I use presentModalViewController
from one of the view controllers inside the master pane, the entire contents of the master pane end up getting rotated 90 degrees when the modal view controller is dismissed. The next time a modal view is presented and dismissed, it will rotate back again.
It is possible to drag the master or detail view offscreen, while the behaviour would be to block dragging at a certain point.
Screenshots:
http://ow.ly/i/41Jp
http://ow.ly/i/41Jq
As a test using the demo application I am trying to replace the detail view with another controller.
I instantiate my new detailviewcontroller and try and use MGSplitViewController:setDetailViewController and nothing happens.
I can trace the code till it hits [self layoutSubViews] but the view doesn't change.
What am I doing wrong here?
Ugh. Scratch all that for now if you've already read it. I'm thought I understood what is going on but I don't have a handle on it.
If I dismiss my modal view controller, it crashes due to this line of code:
} else if (!inPopover && _hiddenPopoverController && _barButtonItem) {
// I know this looks strange, but it fixes a bizarre issue with UIPopoverController leaving masterViewController's views in disarray.
[_hiddenPopoverController presentPopoverFromRect:CGRectZero inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
It crashes with the following raised exception:
'Popovers cannot be presented from a view which does not have a window.'
in order to fix this, I added (... && self.view.window) at the following condition:
else if (!inPopover && _hiddenPopoverController && _barButtonItem && self.view.window)
I didn't test it thoroughly but it seems it has fixed my issue.
The MGSplitViewController is in a window, but I guess that the modal is presented into another UIWindow which is why it temporarly has no UIWindow property set.
interfaceOrientation on the master and detail view controllers is set for portrait even when it's in landscape. Other than that, things are working well for me and I'm finally able to layout my views the way I want without having to implement it all myself. Thank you.
I know that MGSplitViewController is not being maintained, but i'm posting this here anyways hoping that someone will stumble upon this and might share his experience and possibly a solution.
My objective is basically to use UISplitViewController inside a UITabBar. UISplitViewController doesn't work well inside a UITabBar. Specifically, UISplitViewController splits apart when device orientation changes. Anyways...
Since UISplitViewController didn't work for me, i turned to MGSplitViewController. And now it seems that it's not a workable solution to be used with UITabBar either. Im running into all sorts of problems. Mainly the following:
I have a tab-bar with 3-4 tabs. Each one contains a MGSplitViewController. In general, the MGSplitViewController contains a Master (UINavigationController) and a Detail (UIViewController). When i rotate the device, the content inside the visible UITableView area is misaligned/disturbed. Scrolling the UITableView to show new cells fixes the misalignment. The Master also has a Navigation bar and a search bar on top of the UITableView, and orientation change doesn't affect them. I'm not getting this issue with UISplitViewController. Any solutions, suggestions, pointers?
Because self.allowsDragging = NO; is already equal to 0x0, the method - (void)setAllowsDragging:(BOOL)flag fails the condition which leave userInteractionEnabled to it's default setting (YES)
Setting the masterViewController as the UIPopoverController's content view causes a SIGABRT.
The line:
_hiddenPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.masterViewController];
Causes the following exeception:
Terminating app due to uncaught exception 'NSGenericException', reason: 'The content view controller argument must be the root of its associated view controller hierarchy.'
You can avoidt his by "de-parenting" self.masterViewController prior to creating the UIPopoverController. However, you then lose reference to the splitViewController from self.masterViewController.
setViewControllers should check for controller!=[NSNull null] before removing from the views parent. The following code should work as a replacement.
(void)setViewControllers:(NSArray *)controllers
{
if (controllers != _viewControllers) {
for (UIViewController *controller in _viewControllers) {
if((NSNull *)controller != [NSNull null]){
[controller.view removeFromSuperview];
}
}
[_viewControllers release];
_viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
if (controllers && [controllers count] >= 2) {
self.masterViewController = [controllers objectAtIndex:0];
self.detailViewController = [controllers objectAtIndex:1];
} else {
NSLog(@"Error: %@ requires 2 view-controllers. (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
}
[self layoutSubviews];
}
}
Trying to create an universal application with MGSplitViewController will crash upon start on an iPhone running iOS 3.x with the message
Symbol not found: _OBJC_CLASS_$_UIPopoverController
The issue can be resolved by replacing
_hiddenPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.masterViewController];
with
_hiddenPopoverController = [[NSClassFromString(@"UIPopoverController") alloc] initWithContentViewController:self.masterViewController];
in MGSplitViewController.m
The MGSplitViewController class only contains the constructors initWithNibName:bundle: and initWithCoder: but no initWithFrame: constructor.
As I am trying to create the MGSVC from code I get some problems because setup does not get called in that case.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.