UINavigationController autoresizing views behavior - iphone

I've read in Apple's documentation about UINavigationController's resizing behavior and it hasn't been much of a problem until now.
I have the following code to set up my UINavigationController's view:
navController.view.frame = CGRectMake(0, 40, 320, 420);
and this is sufficient until the view is obscured by a modal view, at which point the view is resized to the default size somewhere between calls of viewWillAppear and viewDidAppear (as UINavigationController inherits from UIViewController).
I'm attempting to keep a banner visible above the UINavigationController (in the 40 by 320 space left available) but this banner is consistently obscured as described above.
Is there a way to surpress UINavigationController's resizing behavior without subclassing UIViewController myself?

In interface builder, you can uncheck the auto-resize checkbox.
In code, it's
[myNavController.view setAutoresizesSubviews: NO];

I'd try
myNavController.superview.autoresizesSubviews = NO
and obviously check myNavController.autoresizingMask
As a last resort, subclass its superview and reimplement layoutSubviews

Related

Storyboard UIScrollView contentSize?

I feel like I have touched on every single possible cause for stopping this, but I have a UIScrollView in my Storyboard hooked up with an outlet and in the viewDidLoad I set the contentSize so that I can scroll (yes bigger than my frame size)!
However, whatever I change, I just can't scroll! I have a couple of textfields in my scrollview and bouncing enabled so I can see that when testing its moves up and down with my subviews in it but whatever I set the contentSize to I just can't scroll.
Anything I might be missing/should check? Is this a known issue with UIScrollView being used in a storyboard?
Whats even stranger is, I can do something like this:
[scrollView setBackgroundColor:[UIColor blueColor]]; and I have a blue scroll view! But setting content size fails.
Edit
My only code (otherwise scrollview is just dropped into storyboard view controller):
-(void)viewDidAppear:(BOOL)animated
{
[scrollView setContentSize:CGSizeMake(320, 640)];
}
Logged frame, comes out as expected:
width: 320.00
height: 504.00
Edit 2
Turns out that removing any subviews of the scroll view in my storyboard lets it scroll just fine. If I add any subview to it at all via the storyboard, even a blank brand new UIButton it just won't apply the contentSize/allow scrolling.
use ViewDidLayoutSubview
- (void)viewDidLayoutSubviews
{
[_scrollView setContentSize:CGSizeMake(320, 500)];
}
UIViewController's method invoke sequence is as below
awakeFromNib
viewDidLoad
viewWillAppear
viewWillLayoutSubviews
viewDidLayoutSubviews
viewDidAppear
viewDidLoad is not a good place to put code that relies on frame sizes of IB objects. If you log the contentSize of your scroll view in viewDidLoad, you will see that it's (0,0). Move the code (where you set the content size) to viewDidAppear, and it will work properly.
Check these
User Interaction enabled
Outlet connected
Included contentsize greater than bounds
scrolling Enabled
eg
scrollView.contentSize = CGSizeMake(320, 640);
My storyboard looks like this for scrollview [working]
I had exactly the same line of code in viewDidAppear and it did not work
Moved it to viewDidLayoutSubviews and it worked correctly.
[scrollView setContentSize:CGSizeMake(320, 500)];
Thanks trick14 for the answer.
The issue is most probably with Auto Layout. UIScrollView needs special attention when using AutoLayout.
Quick-fix - bind one of the scroll's subviews to the top AND bottom space of it's superview (the scroll view).
Long story:
Questions on SO:
UIScrollView not scrolling regardless of large contentSize,
UIScrollView will not scroll, even after content size set,
UIScrollView doesn't use autolayout constraints
Apple's Documentation:
https://developer.apple.com/library/ios/technotes/tn2154/_index.html
Trip14's answer worked for me. In swift I coded it as:
override func viewDidLayoutSubviews() {
(self.view as! UIScrollView).contentSize = CGSizeMake(600, 600)
}
This seems to be a similar issue. Other Story
It might be an issue with auto layout or constraints in the storyboard.
the best way with the storyboard.:

UIViewController frame

I've got the following setup.
A pagingScrollViewController with a UIScrollView as it's view (self.view = scrollView).
In that scrollView I add the view of a rootViewController as subview.
The view of the rootViewController is an UIView on which I add one or the other view (depending on internal logic).
The UIScrollView is initialized with a frame equal to the applicationFrame, so 0, 20, 320 , 460. Which is fine because of the statusbar on top.
The problem comes when adding the rootViewController's view to the scrollview. In the creation process of the rootViewController it's view is setup in -loadView which is still commented out in my case. So the standard appel loadView is processed.
It gives me a view which also has a frame of 0, 20, 320, 460. Which is not as I would like to see it as now the View of the rootViewController is 40 pixels removed from the top of the actual iphone screen.
Now, this is of course easily fixed by manually setting the rootViewControllers view in -loadView or assigning it a frame where the y is set to 0 in -viewDidLoad;
But I cannot imaging that that is the way apple intended this to be done. I'm not using Interface builder, so maybe that's the problem, apple intends me to use IB, but im stubborn on that subject :)
Am I using viewControllers the wrong way? This seemed a nice way to split the logic of the scrollView away from the logic of the other view's.
What would be the correct way to add the view of a second UIViewController to the view of a first UIViewController. In which the first viewController.view receives a frame of 0, 20 , 320, 460. And de second controller.view a frame of 0, 0, 320, 460 (so basically the bounds of the first controller.view)
There's a lot of use of the word controller and view in there, hope the question is clear though.
To answer my own question...
Ravin was right.
After reading up on the loadView method and apple's view controller programming guide I've come to the conclusion that this is the default behavior of the system. If you want anything else, override -loadView and do it yourself. Actually apple states that if you don't use an NIB, you SHOULD override -loadView to create at least a basic simple view.

UIView subview is not autorotating or auto-sizing for iPad

In my iPhone app, I have a UIViewController with two subviews: a main UIView (let's call it mainView), and a secondary UIView (let's call it secondView), which is usually hidden but is sometimes shown (e.g. user settings). In my UIViewController, self.view is set to mainView. When the user switches to the subview, I call [self.view addSubview:secondView] and when the user switches back to the main UIView, I call [secondView removeFromSuperview].
There are two issues which I am dealing with at present:
When the user rotates the iPhone or iPad, the main UIView (mainView) autorotates properly and all of its UI items follow its autoresize rules which I have set up in Interface Builder. However, when the secondary UIView (secondView) is displayed, and the iPhone or iPad is rotated, the secondView & all of its UI items do not follow their autoresize rules. I have found that when I set self.view = secondView, and then rotate the device, the view rotates properly.
In the iPad specifically, when I pull up the secondView using [self.view addSubview:secondView], it is not resized to fill the full screen just as the main UIView has been resized for the iPad version. So I end up with a screen that displays the mainView UIView in the background, and the secondView UIView in the top-left corner without taking up the whole screen.
My instinct tells me that these two issues are related to one another. Has anyone else experienced these kinds of issues with secondary UIViews which they add to their UIViewControllers using addSubview:?
When using addSubview,
[secondView setFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
Not very elegant. But it worked for me:
I had a similar problem. I solved the size issue by setting the content mode of the view.
Exp:[_yourView setContentMode:UIViewContentModeScaleAspectFill];
I hope this helps...

UIView Subview Does not autoresize on orientation change

In my iPhone app, I have a view controller with two views (essentially, a front & back view). The front view is the main UIView, and the back view is a secondary UIView which is added as a subview using [self.view addSubview:backView] when showing the back and [backView removeFromSuperview] when hiding it. However, when the orientation changes, I have the following issue: the main UIView (frontView) rotates & all of its elements resize properly, but the secondary/subview UIView (backView) does not rotate & all of its elements do not resize properly. Does anyone have suggestions on how to make the secondary UIView autoresize properly according to the rules I have set in Interface Builder?
In the end, the solution I found was simply to separate my UIViews into separate UIViewControllers, and make sure that any views that I wanted to be able to rotate only had one UIView.
If I understand correctly, at the time of rotation 'backView' has been removed from it's superview, yeah? If so, that's the cause of the problem. The autoresize property determines how the view resizes relative to it's superview. If it doesn't have a superview it won't resize.
Perhaps using [backView setHidden:YES] instead of [backView removeFromSuperview] will be sufficient for your needs.
I had the same problem, here is how I fixed it based on imaginaryboy's
suggestions (thanks!)
Add the backview to the viewcontroller at viewDidLoad and hide it at the same time. Show it when needed, Hide it again. Set the resizing of the backview to UIViewAutoresizingFlexibleWidth in IB (or code I guess, I used IB)
Not that this is the same problem, but I found a similar problem when adding 2 subviews in my application:didFinishLaunchingWithOptions method. Since your reference above is using [self.view addSubview:view], I would understand that to mean that self is not your UIWindow. When adding an additional view controller to your App Delegate window (UIWindow), the second view controller will NOT receive any rotation events and will never rotate. Only the first view controller added to UIWindow will rotate. See:Technical Q&A QA1688 I believe this also affects views added after the first view where the first view is later removed from the superview.
I ended up following the suggestion I read elsewhere to use separate views for each orientation, thereby eliminating the need to worry about resizing behavior. As always, YMMV.
Or; if you want to avoid an additional controller, you can achieve the same effect by setting view.frame in willRotateToInterfaceOrientation:: like so
if(UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) ;//set stubborn view.frame for landscape orientation
else ; //set stubborn view.frame for portrait orientation
Although it feels like a hack; it's simple.

Resizing UITableView on RootController

Is it possible to resize the UITableView on the RootController of a nav based app? When RootViewController.xib is opened in IB, there isn't a view. Just the UITableView. Clicking the inspector and then the little yellow ruler, frame height is grayed out. I'm adding a toolbar programmatically to the RootViewController:
[toolbar setFrame:rectArea];
That works fine but the bottom cell in the tableview is partially hidden because the tableview doesn't know about the toolbar.
The easiest way, is to adjust the contentInset (which is inherited from UIScrollView). Resizing by setting the frame can cause crazy drawing bugs in cells.
For example, if you are trying to resize a tableview for the keyboard, do something like this:
tableView.contentInset = UIEdgeInsetsMake(0.0, 0.0, 216.0, 0.0);
tableView.scrollIndicatorInsets = tableView.contentInset;
Hope that helps someone. This way worked best for me.
Yes, but you need to have a ViewController (not a UITableViewController) as the root controller for the nav, and wrap the actual UITableView in the UIViewControllers view.
You can still have the UIViewController conform to the UITableViewDelgate and Datasource protocols, and use all the same methods you have now in your UITableViewController.
P.S. you'll get more responses if you use the plain "iphone" tag.
You could also just set the Content and Scroller inset of the tableview
I encountered a similar issue when attempting to display the detail controller by itself, see: http://vimeo.com/13054813
The issue is that the SplitView controller applies its own transform to the sub-controllers, taking them out of the orientation detection loop, which blows goats and seems incredibly 'hackish' for built-in classes. (The video illustrates what happens when you make the detail view the root view, then add it back to the split view and make the split view root while in landscape; you get double rotation of the detail view.)
Unfortunately I've again run into these transformation issues while attempting to resize a SplitViewController's detail sub-view in response to the keyboard appearing/disappearing. In portrait, all works fine, in landscape it's fscked.
Yes, adjust the contentInset and scrollIndicatorInsets are the convenient way to resize the UITableView.
As the answer of Sam Soffes posted, I succeed resize UITableView in UITableViewController for the bottom UIToolbar.