Prevent resizing of a view controller presented as a sheet? - objective-c

Is there a way to prevent a view from being resized if the view controller is presented as a sheet using the method presentViewControllerAsSheet or using a segue of style "sheet"?
Note that modal/show segues can be implanted to a window controller which can be set as non resizable from the storyboard itself. Segues of type popover are non-resizable by default.

Have you tried setting your sheet view controller's -preferredContentSize? Failing that, what about adding width and height NSLayoutConstraints to the view controller's view on -viewDidLoad?

This worked for me. The sheet is no longer resizable:
override func viewWillLayout() {
preferredContentSize = view.frame.size
}

None of the other solutions worked for me, so I ended up using an NSWindow as the sheet controller (rather than a NSViewController on its own).
Declare an NSWindowController object in your header file:
NSWindowController *detailWindow;
To open the window in the form of a sheet, use the following code:
NSStoryboard *storyFile = [NSStoryboard storyboardWithName:#"Main" bundle:nil];
detailWindow = [storyFile instantiateInitialController];
[self.view.window beginSheet:detailWindow.window completionHandler:nil];
To close the window:
[self.view.window endSheet:detailWindow.window];
In order to stop the window sheet from being resized, simply set the NSWindow minimum/maximum size in interface builder:
That's it, super easy! (Don't forget to set the window controller, as the initial controller).

the above methods did not work for me .
self.view.autoresizesSubviews = NO;
this line in viewcontroller should do the trick if the above methods didnt work

Related

How to set index of UIViewController as background

I'm trying to set background to the entire app from the code:
UIViewController *controller = [[UIViewController alloc] init];
controller.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background#2x.png"]];
self.window.rootViewController = controller;
[self.window makeKeyAndVisible];
In the Storyboard I have a simple button in the main UIViewController. In the AppDelegate.m I set that code above, but, I background has added, they is in front of the text that is in the Storyboard.
I want to know how can I set that background from the current index to the last index in the stage.
You can create a subview, set the background image in that subview, frame it to the right size and then send that subview to a position "behind" everything else:
[mainView addSubview:backG1];
[mainView sendSubviewToBack:backG1];
Well, wenn you use a storyboard at all, AND declare it in your project settings as THE storyboard of your app, then you are not supposed to create and set the root view controller in your app delegate.
Both of them is perfectly fine, but one is the interface builder/storyboard option and the other is the programmatical way. Both ways just don't agree!!!
If you want to go for storyboards, which I encourage you to do, then give your root view controller an ID and in aoru ypp delegate method didFinishLoadingWithOptions: fetch it from the storyboard and set its background view then.
Have in mind: When you use a background view then you need to set all the background colours of all your view items (that may be tables, table cells, cell content views etc. pp.) to clearColor.
When you set an initial view controller in code (in AppDelegate.m, under didFinishLaunchingWithOptions), then it overrides the root view controller in your storyboard.
You can either set your view controller's background in the storyboard, or initialise it like you did - but then you need to create all other UI elements in code as well.

Autolayout with custom segues

I am attempting to cross-dissolve between two view controllers with a custom segue, the segue initiates properly and performs the animation as intended - however when in landscape mode the destination view controller appears in its portrait layout for the duration of the animation. Once the animation completes the destination view controller "snaps" to its landscape layout. Both of the view controllers are set up using auto layout.
Below is my custom segue's "perform" method:
- (void)perform
{
UIViewController *srcController = self.sourceViewController;
UIViewController *dstController = self.destinationViewController;
dstController.view.transform = srcController.view.transform;
[UIView transitionFromView:srcController.view
toView:dstController.view
duration:self.animationDuration
options:self.animationOptions
completion:self.animationCompletionBlock];
}
Is it necessary to manually tell the destination view controller to trigger autolayout before it is displayed? And if so how would this be performed? Using the built-in segue with a cross-dissolve does not appear to encounter this problem, I have attempted (without success) to determine what it is doing that my custom segue is not.
This has had me stumped for a while, any help would be appreciated and please let me know if more details are needed.
So it turns out that the solution to this problem was more simple than I would have imagined. Adding the following line ensures the destination view controller has the right bounds when it lays out its elements:
dstController.view.bounds = srcController.view.bounds;
So the rest of the code becomes:
- (void)perform
{
UIViewController *srcController = self.sourceViewController;
UIViewController *dstController = self.destinationViewController;
dstController.view.transform = srcController.view.transform;
dstController.view.bounds = srcController.view.bounds;
[UIView transitionFromView:srcController.view
toView:dstController.view
duration:self.animationDuration
options:self.animationOptions
completion:self.animationCompletionBlock];
}

UIModalPresentationFullScreen not working in iPad landscape mode?

I have added a ViewvController(B) as subview on ViewController(A). In ViewController A(SuperView) UIModelPresentationFullScreen working fine. But when am calling UIModelPresentationFull in ViewController B(SubView) it modelview showing in Portrait mode and that is also not fully viewed. How to solve this problem. Can any one help me please. I have tried 2 days.
This is what I tried in both the superview and subview...
picFBCapture *fbCapt = [[picFBCapture alloc] init];
//[self.navigationController pushViewController:fbCapt animated:YES];
//fbCapt.modalPresentationStyle = UIModalTransitionStyleFlipHorizontal;
fbCapt.modalTransitionStyle = UIModalPresentationFullScreen;
[self presentModalViewController:fbCapt animated:NO];
[fbCapt release];
Thanks in advance..
The problem is that if you add a view controller as a subview it's not connected to the view controller hierarchy and thus certain things doesn't work. You should avoid adding view controllers as subviews whenever possible, since this is not how Apple intend view controllers to be used, but sometimes it can't be avoided.
If this is one of those cases when it can't be avoided you should save a reference to view controller A in view controller B and then call presentModalViewController: on view controller A (that is connected to the view controller hierarchy) instead of self (view controller B, that isn't connected).
EDIT: In controller A you probably have code looking something like:
[self.view addSubview:controllerB.view];
In conjunction to this line add:
controllerB.controllerA = self;
I hope you know how to create properties, but if not here's a hint:
#property (nonatomic, assign) UIViewController *controllerA;
The rest you should be able to figure out using Google and the documentation.
You will have to handle viewController B's view in landscape by yourself. Since viewController B has been added as a subview, its view controller will not be handling its landscape orientation. The UIModalPresentationFullScreen style (landscape and portrait) will work only if viewController B is shown, ie not as subview but as a full view itself.

Adding a Navigation Controller to a View based Application adds top margin

I am trying to programmatically add a Navigation Controller to my View based Application. This is the code I am using (this code gets called after a button press in a view controller):
MainMenu *control = [[MainMenu alloc] initWithNibName: #"MainMenu" bundle: nil];
UINavigationController *navControl = [[UINavigationController alloc] initWithRootViewController: control];
[self.view addSubview:navControl.view];
[control release];
That works, but this ends up happening:
Notice the odd margin above the Navigation control.... My View controller that I am adding the Navigation Controller to has a gray background which you can see.
Any ideas??
If you have a better way of adding a Navigation Controller to a View based Application I am very open to suggestions!
Thank you in advance!
Thank you both for your response, but unfortunately, wantsFullScreenLayout set to YES or NO in the code didn't have any effect. I was able to push the Navigation Controller up by 20 using this line of code:
self.navigationController.navigationBar.frame = CGRectOffset(self.navigationController.navigationBar.frame, 0.0, -20.0);
but then what happened was that the View Controller did not move up with the Navigation bar and left a gap below the Navigation Bar and the View Controller. What eventually worked was checking the Wants Full Screen checkbox in IB in the MainWindow view controller that is automatically generated when you set up a view based application.
The gap you are seeing is the same height as a status bar. Check the status bar settings in your NIB file.
Chances are you want to make the UINavigationController the root view controller for the window, rather than whichever view controller you have now. That would be the better way to do it.
The reason you're seeing that extra margin at the top is because UINavigationController normally expects that it will be sized to fill the entire screen (except perhaps a tab bar at the bottom, if it's inside a UITabBarController), and therefore expects that the top edge of its view will be under the status bar if the status bar is visible. Therefore, it places its navigation bar 20 pixels below the top of its view to leave space for the status bar, without bothering to check whether its view actually is under the status bar. Interestingly, sometimes a re-layout operation will perform this check, but that's unreliable. What I've found works well in a situation like this is to set the UINavigationController's wantsFullScreenLayout property to NO. Then ti doesn't try to leave room for the status bar, so everything works as expected.
I've been struggling with this same issue this morning. Since setting the wantsFullScreenLayout property doesn't seem to have any effect, I resorted to using a little subclass, which worked fine:
#interface MyNavigationController : UINavigationController
#end
#implementation MyNavigationController
- (BOOL)wantsFullScreenLayout;
{
return NO;
}
#end
Its so simple to remove that gap..
self.navigationBar.view.frame = CGRectMake(0, -20, 320, 480);

UISplitViewController non root, forcing custom rotation methods, makes master view dissappear

I'm trying to add a split view inside of a tab bar, and since the split view isn't the root, it doesn't properly get the rotation notifications, so the delegate's methods are never called to add the button to the toolbar in the detail view.
I've rigged it up so I can generate the popover when rotated, but when this method is called, the view dissappears from the landscape mode, and if you activate it and then rotate back into landscape, it's a black empty box where the master view used to be. How do I get rid of this occuring?
-(void) displayPopover:(id)sender
{
//Toggle the popover: if it's showing, hide it
if (popoverController != nil && [popoverController isPopoverVisible])
{
[popoverController dismissPopoverAnimated:NO];
}
else
{
//Create a Popover displaying the master view
if (popoverController == nil)
{
popoverController=[[UIPopoverController alloc] initWithContentViewController:self->rootController];
popoverController.popoverContentSize=CGSizeMake(300, 500);
}
[popoverController presentPopoverFromBarButtonItem:[detailController.toolbar.items objectAtIndex:0] permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
}
You will need to remove all the objects from window using:
[appdelegate window ] subviews] objectAtIndex:0] removeFromSuperview];
Then add your splitview to the window, you can get the view callbacks.
I would recommend either finding a way to get your SplitViewController to be root, or creating a custom subclass of the UISplitViewController that allows for non-root placement.
I really like what Matt Gemmell did here: http://mattgemmell.com/2010/07/31/mgsplitviewcontroller-for-ipad
Using a custom subclass like Matt's will allow you to benefit from all the same delegate methods that a SplitView as root would allow. I used it in a project where I wanted my SplitView to appear as a modal - almost impossible with a traditional UISplitViewController.
so your split view has rotation enabled (shouldAutorotateToInterfaceOrientation:) now you have to make sure that the tab controller has also rotation enabled (should be the appDelegate, am I right?) AND you have to make sure that every other view that is in your TabBar has also rotation enabled!
so if your TabBar contains 2 tabs you have to set the rotation in 3 classes.