views:

3010

answers:

3

I'm learning to develop for iPhone (programmatically, I don't like IB). I only use IB for the frames of things, so I design in IB but only use it to check each control's frame. Something I've gotten very confused about is the frame of a UIView. First of all, if you do not implement loadView in a view controller, it automatically creates an empty UIView (and I've noticed that its black) and assigns that to self.view, correct? What about the frame? does it automatically figure out what the frame should be? I mean, it needs to be different depending on the if there is a status bar, if there's a tab bar, a toolbar, the orientation. In my tab bar app, it seems no matter what I set frame of my uiview is, it still looks fine. And also, the frames for UIView seem messed up in IB. Like the y value of a UIView taking up the whole window (except status bar) is 0, when it should be 20, because the status bar takes up the top 20 pixels. And in IB a view in a tab bar controller has a y value of 411, even though it begins right under the status bar. And whenever I NSLog a frame (the four numbers, view.frame.origin.x, view.frame... etc.) the x, y, width and height are always 0.. Can someone who understands it please explain it to me? Thanks!!

Ok, this is weird... This:

CGRect test = CGRectMake(0, 20, 320, 460);
NSLog(@"%d %d %d %d", test.origin.x, test.origin.y, CGRectGetWidth(test), CGRectGetHeight(test));

gives output:

0 0 0 1077149696

??? What's with that?

+4  A: 

First thing you should note is that CGRect's origin and size members use float, so in your NSLog statement you need to use %f, not %d. So for example,

NSLog(@"%f %f %f %f", test.origin.x, test.origin.y, test.size.width, test.size.height);
keno
thanks, they show the correct numbers now. But what about the rest of my question?
Mk12
Why are they floats though.. each 1.0 represents 1 pixel, and you can't have half a pixel..
Mk12
I'll look into the rest of your question today when I have access to a mac box. As for the float usage, you would have to ask Apple that question :)
keno
A: 

Pixel sizes are floats because on the desktop you need precise math when doing scaling and want to support proportional sizing. If you stick to integers and the window size is expanded by, say 1.2x, integer round-off will throw things out of line. They kept the same thing on the iPhone because you can have subviews that get auto-sized and floats offer more control over size and position.

As for the view positions, if you go into IB and select a view and check the "View Attributes" inspector you'll see one of the options is to show "Simulated Interface Elements." By default it has the Status Bar enabled (with Gray) and it allows for its height in the interface. If you check the size tab in the inspector, the view height is actually set to 460 (allowing for the 20 pixel status bar).

You can choose to include a top bar or a bottom bar and it will "simulate" those by adjusting the content height for you. This is just a positioning simulation so you can lay out your controls. At runtime, it's assumed you'll load the view into the proper viewcontroller which will have the proper chrome so it should all look right.

A lot of IB numbers are there for relative positioning. When you add the view to a navcontroller or a tabview, this view becomes a child of those parent views and by default they autoresize subviews. So if you've "simulated" for that top bar in IB, your controls should all be lined up properly and flow into the right place and you should see what you expect (of course, depending on what parent control ends up with your subview as a child).

BTW, you're missing out a lot of convenience by not using IB to wire up the controls and connecting them to IBOutlets. It really helps take out a lot of manual effort and extra code. It's like Superman refusing to use his X-ray vision and instead deciding to punch through walls :-)

Ramin
but how come in IB for example if you have a window, inside the window a view, its correctly 320 by 460, 20 pixels for the status bar, but the Y coordinate is 0, when it should be 20.. As for using IB, I don't really see the point in it for simple iPhone UI's, I think it's better for complicated desktop applications. And its much more satisfactory knowing it was 100% coded by me :-).
Mk12
I believe IB is showing coordinates for bounds (local coordinate) instead of frame (parent coordinate). So in parent coordinates a view might be at y=20 but in its own coordinates it's at y=0 with the size the same either way (if it was simulating having the status bar).
Ramin
in the drop down box it says 'frame' and 'layout' and 'frame' is selected... if it was bounds, it should say 'bounds'. But I guess if it was another nib it wouldn't know what the parent view is... I don't know.
Mk12
IB has no way of knowing what parent view a given view is going to end up in (if it did, I'd be worrying about time-space continuum issues :-) So it gives you its best guess. It's up to you to tweak the UI to make sure the view ends up where you put it. I personally look at the bounds settings instead of frame because frame will change at runtime once the view is placed.
Ramin
A: 

Answer: IB doesn't always show correct origin/location coordinates, and some things, like UITabBarController, resize the view to be what they want it to be no matter what you set it.

Mk12