Xcode 6 Interface builder subview size issue - ios

I was using a xib to do some simple view layouts and noticed that the size of my subviews was incorrect in relation to the size of the view itself.
I decided the last time I tried to ask this question I may have already had too complicated of a product for people to fully understand what I was asking.
Here is a simple view:
It is exactly as I would like it to be position and exactly how I would have expected to lay itself out as shown here:
If you notice at the bottom there, I did a log of the size of the views. The log is as follows in my viewDidLoad lifecycle method.
NSLog(#"%f, %f", [[UIScreen mainScreen] bounds].size.width, self.blockView.bounds.size.width);
Why is it that the view width is in no way close to the actual width reported my the application's view size? I am trying to cast a shadow under my subview but since programmatically it thinks the view is much wider, this wont work. Also positioning any subviews programmatically in the purple view shown there will not work either since the frame does not match the expect frame.
PLEASE HELP.
thank you.
EDIT: LACK OF SLEEP LEADS TO FORGETTING LIFE CYCLES....

You should log the view width in viewDidAppear.
viewDidLoad is called after the view controller has loaded its view
hierarchy into memory.
By the time viewDidLoad is called, auto layout hasn't finished calculating your view position according to the constraints of the view.

Related

iOS Auto Layout UIView Drawing cycle

In one of the WWDC videos, Apple said that the layout is done from top down, ie from superview to subview (after constraints are calculated from bottom up). Display is also done from top down.
My questions are:
1. At what point in the viewcontroller is a view's frame (origin and size) determined? I tried to log the size of a view (defined using auto layout), but it was always 0 0 0 0, which is odd, because the view is already generated in the simulator;
For an autoresized view, when is view.frame available?
Same question, except this time it is UIImageView.frame. I tried to log to console, even though the size is fit into the constraints, the logged UIImageView frame is 0 0 width_of_original_image height_of_original_image. But for other views like labels, the frame is printed correctly on the console.
It seems like that there is a mysterious auto layout engine that performs transform, and nobody knows what is going on inside the engine, but to check what is thrown onto the simulator display to figure out how the view was rendered by this engine???
It's not mysterious. It's quite simple! Think of constraints as instructions written down on pieces of paper - the views. Every once in a while, it's layout time! The runtime collects the pieces of paper from the views in order and obeys them - and so you end up with laid out frames.
So if you check sizes of things before layout time, you get the wrong answer because it hasn't happened yet.
And when is layout time? It's whenever the runtime sends views layoutSubviews - in fact, the runtime obeys constraints and performs layout during layoutSubviews. And your view controller can hear about this before or after, with viewWillLayoutSubviews and viewDidLayoutSubviews.
I think the part that confuses beginners the most is what happens when a view controller comes into existence. viewDidLoad means it has a view, but that is all; neither the view nor its subviews are in the interface yet, so obviously there can be no layout. Considerably later, we get viewWillAppear:, the view goes into the interface, and now we get layout. So if you check sizes in, say, viewDidAppear:, they will be right.

iOS - viewDidLayoutSubviews called before auto-layout completed on iOS7

We're currently having a problem that only seems to affect iOS7 devices.
Within our .xib file we have two views within a container view (i.e.: not at the top level of the view hierarchy) that need to be circular on display. The views have constraints applied to their position and horizontal spacing within the container, and an aspect ratio condition requiring they are square. The views should expand in width/height on larger screen sizes, respecting the constraints described.
In our VC, we have the following in viewDidLayoutSubviews to force these views to appear circular:
- (void)viewDidLayoutSubviews {
self.progressContentContainerView.layer.cornerRadius = self.progressContentContainerView.frame.size.width/2;
}
This seems to work fine on iOS8, however on iOS7 there is a period after the view has been displayed where the constraints have not yet been applied and the size of the view/views is incorrect (see attached screenshots). This resolves itself and correctly renders a circle after half a second. This only appears to happen when the views that we intend to be circular are NOT at the top level of the VC's view hierarchy which seems to imply that viewDidLayoutSubviews is called before the subviews of subviews have also been laid out.
My guess is that we could potentially fix this issue by subclassing UIView for the nested container, adding references to the circular view within this subclass and overriding viewDidLayoutSubviews here to make the cornerRadius adjustment. This seems like a bit of a workaround though and I'm interested to see if there are other options.
Is there a cleaner/more idiomatic solution to this problem?
I know this is an old question but have you tried calling either:
[self.progressContentContainerView setNeedsUpdateConstraints];
or:
[self.progressContentContainerView layoutIfNeeded];

ios: Get size of parent popover from child viewController?

I have a viewController which is presented inside a popover. I'm trying to figure out how to size the viewController's view (viewController's self.view) to match the popover.
I would think the view would automatically be size to fit into the popover; for some reason, it isn't. The view's frame is the size of the entire screen, for some reason.
How do I either: detect the size of the surrounding view controller so I can resize the view; or, cause the view to automatically size itself to the popover?
Note: This is a class which is embedded into someone else's app, so I have no control over the popover size itself.
Figured out what I was doing wrong: I was looking at the frame size in the viewDidLoad method. It's not always valid at that point, for some reason.
The correct place to check the frame size is viewDidAppear; it seems to be valid there. Admittedly, though, I haven't checked this in every single corner case, so YMMV.
Override contentSizeForViewInPopover for your view controller and return the size you need the popover to have. So, it somehow works the other way around, the contained view controller lets the popover know how large should it be. The popover is 320px x 1100px by default I think. If you overwrite the method I mentioned above, you'll make it as large as you want it to be, even if the code is embedded in an app and you don't have control over it.

UIScrollView not working

I have a UIScrollView with a View inside of it. Inside of that view is a bunch of buttons, labels, etc that fit in the View when in Portrait mode...When the iPad is rotated, I want the scrollView to kick in so the user can scroll to the bottom of the view. The app runs, but when I rotate it, the scroller never works...I believe I've wired everything up correctly and I have this code in the viewDidLoad event:
[scrollview addSubview: masterView];
scrollView.contentSize = [masterView sizeThatFits:CGSizeZero];
Is there something else I am missing? Do I need to modify the size when the iPad rotates?
thanks
There may be a problem with the content size of the UIScrollView. Without the contentSize being set larger than the actual scrollView size, scroll bars won't be shown.
You can code this in with something like this:
[scrollView setContentSize:CGSizeMake(2000,2000)];
And then changing the content size to the actual content size of what you are putting in the UIScrollView (scrollView).
If you look at the results of [masterView sizeThatFits:CGSizeZero] (e.g. NSLog or set a breakpoint in your debugger, I think you will find that it's not what you expected it to be. You might find that masterView has autoResize parameters set (which is common for a view that covers the entire screen), which means that it might, itself, be getting resized too short to fit all of its controls and scrollView is simply grabbing this shortened value itself. Take a look at that CGSize and the problem will be obvious.
I faced similar situation but my case was iPhone.
Remember that content should be larger than scroll for scrollView to kick in.
"Why would you want to go down if everything is visible in front of you ?"
use the following code:
[scrollView setContentSize:CGSizeMake(intValue, intValue)];
intValue: Integer values setting width and height of scroll.
Even if it doesn't works, don't worry there are loads of other options to figure out the solution:
1. NSLog
2. Breakpoints
3. Put up errors you are getting from console on stackoverflow

iOS: How can I figure out the size of the view in the super view's layout?

When I use self.view.frame.size.height, it gets the height of the child nib, rather than the height of how the view is going to fit into the overall layout. I get the same value using self.view.bounds.size.height and super.view.bounds.size.height.
Any help would be appreciated.
Ask at the right time. Not until the view is ready to appear has iOS figured out what size it will actually be. Move your code that depends upon the view being the right size to viewWillAppear instead of viewDidLoad or an init method.
In Xcode 4 you would select your view controller that contains the UIScrollView and set the 'Simulated Metrics' in the IB Attributes Inspector as follows:
This ensures that your UIScrollView will be set to the correct size to fill the available space at design time. It looks like you are using an older version of Xcode/IB and I can't remember exactly where these settings used to be but they're in there somewhere.
With the layout designed to accommodate the space taken up by the tab bar you should be able to query the size of the UIScrollView at any time and get the correct values.

Resources