UINavigationController donesn't work correctly [duplicate] - ios

This question already has answers here:
iOS 8 UITableView separator inset 0 not working
(43 answers)
Closed 5 years ago.
Code:
UINavigationController * childNaviVC = [[UINavigationController alloc] initWithRootViewController:self.subVC];
[self addChildViewController:childNaviVC];
[self.view addSubview:childNaviVC.view];
[childNaviVC.view setFrame:CGRectMake(0.0f, 0.0f, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
self.subVC.view.frame = childNaviVC.view.frame;
[childNaviVC.view addSubview:self.subVC.view];
[childNaviVC didMoveToParentViewController:self];
what i want to do is add a UINavigationController (childNaviVC) as sub viewcontroller (subVC) of the designated VC, and use the UINavigationController's root viewController to display the content;
the problem which i met is UINavigationController's root view(subVC) size is consistent with UINavigationController's parent VC
the red view size isn't equal to the cyan
thanks

One issue is that you are double adding the subview's view. The addSubView for the subVC will be breaking the auto layout constraints within your navigation controller.
Change your calls to match the following and see what results you get:
UINavigationController * childNaviVC = [[UINavigationController alloc] initWithRootViewController:self.subVC];
[self addChildViewController:childNaviVC];
[self.view addSubview:childNaviVC.view];
[childNaviVC.view setFrame:self.view.bounds];
[childNaviVC didMoveToParentViewController:self];

Add the function viewDidLayoutSubviews to children VC ,and it worked.
-(void)viewDidLayoutSubviews{
self.view.frame=CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
}

Related

bad orientation in screen with multiple viewcontrollers/ views in iOS 7, landscape only (iOS 8 is fine)

I'm using TheSidebarController to implement add a sliding menu into an iOS application. This is the library I'm using, but I've found the same issue in other libraries, like ECSlidingViewController, etc. They essentially work by adding multiple view controllers onto a containing view controller, nothing too crazy.
The issue is, when you make the app a landscape app, all the screens in the container- the menu, the content screen- seem to think they're in portrait mode, and get cut off half way. You can see the issue in this screenshot where the table is cut off:
http://imgur.com/xD5MUei
I've been trying to get this to work in any way I can, and no luck.
The library I'm using + example project can be found here:
https://github.com/jondanao/TheSidebarController
Any help is greatly appreciated :)
EDIT: people are saying I can stretch the table out to make it look normal, but this just masks the underlying problem, which is the app and/or the screens still think they're in portrait orientation. As a quick example, if I take the example project, and in LeftViewController substitute the following code:
- (void)dismissThisViewController
{
UIViewController* vc = [[UIViewController alloc] init];
UINavigationController* pulldown = [[UINavigationController alloc] initWithRootViewController:vc];
pulldown.view.frame = CGRectMake(pulldown.view.frame.origin.x, -[[UIApplication sharedApplication] delegate].window.frame.size.height,
pulldown.view.frame.size.width, pulldown.view.frame.size.height);
[[[UIApplication sharedApplication] delegate].window addSubview:pulldown.view];
[UIView animateWithDuration:.5 animations:^{
pulldown.view.frame = CGRectMake(pulldown.view.frame.origin.x, 0,
pulldown.view.frame.size.width, pulldown.view.frame.size.height);
} completion:^(BOOL finished) {
;
}];
}
The viewcontroller comes in sideways, not from the top.
This was a strange one... I had to set the frame of the content view controller, which made sense, but then I had to reset it every time the content was refreshed:
- (void)setContentViewController:(UIViewController *)contentViewController
{
// Old View Controller
UIViewController *oldViewController = self.contentViewController;
[oldViewController willMoveToParentViewController:nil];
[oldViewController.view removeFromSuperview];
[oldViewController removeFromParentViewController];
// New View Controller
UIViewController *newViewController = contentViewController;
[self.contentContainerViewController addChildViewController:newViewController];
[self.contentContainerViewController.view addSubview:newViewController.view];
[newViewController didMoveToParentViewController:self.contentContainerViewController];
_contentViewController = newViewController;
if ([DeviceDetection isDeviceiPad]) {
_contentViewController.view.frame = CGRectMake(0, 0, 1024, 768);
}
}
Did you check if it's has something to do with the new interface orientation?
https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS8.html
chapter -> Supporting New Screen Sizes and Scales
In CenterViewController.h make the class a subclass of a UITableViewController instead.
Then comment out [self.view addSubview:self.tableView]; in CenterViewController.m.
Done!
In centerViewController.m, when you create the tableview, add this line:
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth;

UIImageView with an image set through IB is taking about 10 seconds to appear once view is called

I have a UIView, and then I added another UIView as a child view to that view using the code below.
TestViewController* holesaw = [[TestViewController alloc] init];
holesaw.view.frame = CGRectMake(0, [UIApplication sharedApplication].statusBarFrame.size.height + 44, holesaw.view.frame.size.width, 454);
[self addChildViewController:holesaw];
[holesaw didMoveToParentViewController:self];
[self.view addSubview:holesaw.view];
child view has a UIImageView with an image that it is set to show through IB. It takes almost 10 seconds to load. Does anyone know why? I have tried the image as both .jpg and .png, and it is only a 200kb image to start with.

UIPopoverController content appears too big

Im trying to present a UIViewController that contains a UIWebView inside a UIPopOverController.
The problem is, that the ViewController inside the popOverController "acts" as if it has an entire screen size so i get scroll indicators and scrolling instead of it just "surrendering" to the container size.
Any suggestions?
NSMutableArray *filesArr = AppDelegate.appContentManager.filesArray;
BIDContent *cellContent = ((BIDContent *)[filesArr objectAtIndex:indexPath.row]);
BIDPreviewPopupViewController *popUpContent = [self.storyboard instantiateViewControllerWithIdentifier:#"previewPopup"];
popUpContent.pageContent = cellContent;
_popOverDisplay = [[UIPopoverController alloc] initWithContentViewController:popUpContent];
[_popOverDisplay setPopoverContentSize:CGSizeMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0)];
popUpContent.view.frame = CGRectMake(0, 0, _popOverDisplay.popoverContentSize.width, _popOverDisplay.popoverContentSize.height);
[_popOverDisplay presentPopoverFromRect:[tableView cellForRowAtIndexPath:indexPath].frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:TRUE];
Forgot about a "hidden" gem in the UIWebView - "scales page to fit". Once I turned this on, all was good!

(kal) calendar/tableview view hierarchy broken in tabbar

I'm using Kal and am having trouble getting it to display properly.
Right now, in the Storyboard, I have a subview of the main view with the tag 1:
I have that subview fitted to the space between the navbar and tabbar:
The problem is that the calendar/tableview (Kal) is not appearing properly in that subview:
First there is that small grey bar above the month (maybe Kal's spacing for the iPhone's info bar?). Then the tableview at the bottom of the calendar is behaving as if it extends far below the tab bar. That is, the cells won't scroll properly, as can be seen by the cell labeled 11:58 which is peeking up from the bottom. (I have scrolled it as far as it will go.)
Here is where I'm setting the delegates and loading the view for the Kal calendar/tableview:
- (void) viewDidLoad
{
NSLog(#"DateTimeViewController - viewDidLoad");
[super viewDidLoad];
self.calendar = [[KalViewController alloc] init];
self.calendar.delegate = self;
self.calendar.dataSource = self;
[[self.view viewWithTag:1] addSubview:self.calendar.view];
NSLog(#"selected date = %#",self.calendar.selectedDate);
}
I had exactly the same problem, I went to KalViewController.m in loadView
and changed the code in this way:
// KalView *kalView = [[KalView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] delegate:self logic:logic];
int width = [[UIScreen mainScreen] applicationFrame].size.width;
int height = [[UIScreen mainScreen] applicationFrame].size.height-93;
KalView *kalView = [[KalView alloc] initWithFrame:CGRectMake(0, 0, width, height) delegate:self logic:logic];
This solved me both the problem of the "header" margin and the table view size.
Just play with the height value.
Play around a little bit with your 'y' value in CGRectMake to get a required frame. try this
KalViewController *kalView = [[KalViewController alloc] initWithFrame:CGRectMake(0,-20,100,320)];
self.calender = kalView;
CGRectMake(<x position> , <y position> , <required height> , <required width>)

iPad custom size of modal view controller

I have a couple of modal view controllers of certain size. I'm trying to avoid the use of custom views (creating full screen black translucent overlay over current view, add the modal view over that view, do the animations, etc) to present it because there is no modalPresentationStyle that fits the size of my controllers.
Now I'm using UIModalPresentationPageSheet but my view is smaller in height and I have an ugly blank space
Desired presentation
_______________
| _______ |
| | | |
| | MyVC | |
| | | |
| ------- |
---------------
Actual presentation
_______________
| | | |
| | MyVC | |
| | | |
| |-------| |
| | blank | |
---------------
If I use the UIModalPresentationFormSheet the container is smaller in width.
I'm trying to figure out how to do it but I don't know if it's possible. What is the solution to the problem of presenting a modal VC smaller than any of the presentationStyles? The only solution is to arrange a "custom modal view controller engine"? Popovers doesn't fit my design requirements :(
As some other users here, I also had the problem that the origin of the modal view controller was not correct. After some experiments, I found a solution that worked for me:
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, <width>, <height>);
}
I obtained the following result (link text) by using:
self.modalPresentationStyle = UIModalPresentationFormSheet;
and by presenting it as a modal view controller. Let me know if you need further help.
All these answers will not work on ios8 SDK.
This will work:
AboutViewController * _aboutViewController = [[AboutViewController alloc] init];
_aboutViewController.modalPresentationStyle = UIModalPresentationFormSheet;
if(IS_IOS8)
{
_aboutViewController.preferredContentSize = CGSizeMake(300, 300);
}
[self presentViewController:_aboutViewController animated:YES completion:nil];
In AboutViewController.m
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
if(!IS_IOS8)
{
self.view.superview.bounds = CGRectMake(0, 0, 300, 300);
}
}
IS_IOS8
#define IS_IOS8 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8)
In iOS 8 you can also use UIPresentationController which gives you more customization options.
I had an issue getting the custom sized modal to center until I figured out what ViewController.view.superview.frame was set to initially. It is determined based on the UIModalPresentation type. superview.center isn't even needed(as far as my testing shows).
Also, I set the coordinates dynamically using [UIScreen mainScreen].applicationFrame, only supporting landscape orientation for now. You have to do a conditional check to support both portrait and landscape by flipping the X/Y and Height/Width values.
Here was my first working solution for iOS 6.0:
ViewController.modalPresentationStyle = UIModalPresentationFormSheet;
ViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:ViewController animated:YES completion:nil];
ViewController.view.superview.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
ViewController.view.superview.frame = CGRectMake(
// Calcuation based on landscape orientation (width=height)
([UIScreen mainScreen].applicationFrame.size.height/2)-(320/2),// X
([UIScreen mainScreen].applicationFrame.size.width/2)-(320/2),// Y
320,// Width
320// Height
);
And then I looked at the previous answer and face palmed. Shortens my solution a tad by replacing the last line with:
ViewController.view.superview.bounds = CGRectMake(0, 0, 320, 320);
EDIT for final solution and remarks.
The best way to do this is to change the bounds property on the superview of the view being presented inside the formsheet. When you present a view modally, the presented view is embedded inside another view.
You should set the bounds property of the superview to the same rect as the view's bounds. First add a private ivar in your class:
#implementation MySpecialFormsheet {
CGRect _realBounds;
}
It's best to do this in viewWillAppear:. Add the following code to the view controller that is being presented modally:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.view.superview.bounds = _realBounds;
}
You need to cache _realBounds in your viewDidLoad method:
- (void)viewDidLoad {
_realBounds = self.view.bounds;
[super viewDidLoad];
}
even for reducing the forma sheet height and width you can use
[self.view.superview setBounds:CGRectMake(0, 0, 450, 480)];
This is my solution for a NOT autolayout view (never tried with autolayout) and compliant with iOS 7 and iOS 8.
At first be sure to call the modal view in this way:
CloudSettingsViewController *cloudController = [[CloudSettingsViewController alloc] initWithNibName:#"CloudSettingsView" bundle:nil];
CGRect originalBounds = cloudController.view.bounds;
cloudController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
cloudController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:cloudController animated:YES completion:nil];
With iOS 8 set the preferredContentSize in the viewDidLoad method of the modal view.
- (void)viewDidLoad {
[super viewDidLoad];
// backup of the original size (selected in interface builder)
height = self.view.frame.size.height;
width = self.view.frame.size.width;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) // versioni successive ios 8
self.preferredContentSize = CGSizeMake(width, height); // this is necessary to get the correct size of the modal view
}
This works ALSO when the modal view needs to display the keyboard on iPad.
With previous versions of iOS 8 you should set the bounds after presentViewController call:
[currentController presentViewController:controlPanelController animated:YES completion:nil];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8)
cloudController.view.superview.bounds = originalBounds;//it's important to do this after
The approaches described above need to be tweaked for iOS7:
// set desired bounds, then call -presentFromViewController:
#implementation PresentedViewController
{
CGRect _presentationBounds;
}
- (void)presentFromViewController:(UIViewController *)viewController
{
self.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
self.modalPresentationStyle = UIModalPresentationFormSheet;
_presentationBounds = self.view.bounds;
[viewController presentViewController:self animated:YES completion:nil];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
if (!CGRectIsEmpty(_presentationBounds))
{
self.view.superview.bounds = _presentationBounds;
_presentationBounds = CGRectZero;
}
}
(This code also works on iOS6.)
Even I was struggling with the same issue for quite a while. After giving few tries from many of the answers given here I came up with a solution that worked for me pretty well.
Here is the code while presenting the view controller.
SomeViewController *sovcObj = [[SomeViewController alloc] initWithNibName:#"SyncOptionsViewController" bundle:nil];
someObj.modalPresentationStyle = UIModalPresentationFormSheet;
someObj.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:someObj animated:YES completion:nil];
someObj.view.superview.bounds = CGRectMake(0, 0, 400, 400); // whatever width and height you want
In the xib (if you are using one) in the 'Simulated Metrics' section select 'Freeform' size.
Apart from this you need to write the below code in your presented view controller (i.e.., SomeViewController in this example)
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 400, 400); // whatever width and height you want
}
This code also works for iOS 7 as well
One solution is to use UIModalPresentationPageSheet to present a page sheet and then immediately resize the modal view. This is fully explained in this answer to another question.
Resize the modal view "after" it is presented using presentModalViewController method.See this link to resize modal View https://coderwall.com/p/vebqaq
You can use MZFormSheetController like this:
MZFormSheetController *formSheet = [[MZFormSheetController alloc] initWithSize:customSize viewController:presentedViewController];
[presentingViewController mz_presentFormSheetController:formSheet animated:YES completionHandler:nil];
This solution worked for me as I had the same issue.
My modal view structure is the following (I use UIModalPresentationCurrentContext at both presenting and presented controllers to achieve transparency in the presented VC)
ModalViewController
> UIView (view) - resized to the same size as the presenting controller but has semi-translucent background - done automatically
>> UIView (contentView) - the true view with the content of the popup - this is the one that got consistently placed at the top of the screen all the time
In ModalViewController I overwrote the following method to fix the positioning issue:
- (void) viewWillLayoutSubviews(){
[super viewWillLayoutSubviews];
CGRect r = self.view.bounds();
self.contentView.center = CGPointMake(r.size.width/2,r.size.height/2);
}
I actually create and size the content view first but in different method.
Hope this helps someone.

Resources