1

I have learned that the proper way to set a UITableView that covers up the whole main view (full width and full height), in a Single View app is, in viewDidLoad:

table = [[UITableView alloc] initWithFrame:self.view.bounds];
table.autoresizingMask = UIViewAutoresizingFlexibleWidth | 
                             UIViewAutoresizingFlexibleHeight;
[self.view addSubview:table];  

note that if a physical iPad 2 is held at Landscape mode, and if the self.view.bounds above is printed inside viewDidLoad, it will show: {{0, 0}, {768, 1004}}. So I thought the idea is: don't worry the width and height not being correct, because the UIViewAutoresizingFlexibleWidth and UIViewAutoresizingFlexibleHeight will take care of setting the correct width and size automatically.

So I actually tried replacing the above first line by:

table = [[UITableView alloc] init];

or

table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];

or even

table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 1004, 768)];

or the ultimately "correct value":

table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 1024, 748)];

when the iPad 2 is held at Landscape position. But now the table won't fully expand to the whole main view. So what is the governing principle here? The width and height can be set incorrectly, but it must be incorrectly at {768, 1004}? It can't be "incorrect" with other values? If no CGRect was given, or some dummy values {200, 200} was given, what should the code in viewDidLoad do to make the table have the full main view's width and height whether it is Landscape or Portrait mode?

nonopolarity
  • 146,324
  • 131
  • 460
  • 740

3 Answers3

1

dont use bounds, use frame instead:

table = [[UITableView alloc] initWithFrame:self.view.frame];
table.autoresizingMask = UIViewAutoresizingFlexibleWidth | 
                         UIViewAutoresizingFlexibleHeight;
KDaker
  • 5,899
  • 5
  • 31
  • 44
  • 1
    setting a subview's frame by using the parent's frame is not a good practice. They are unrelated in fact. If it works, it just happen to work by accident. The "pragmatic programmers" may do it this way, but I won't like to do it by whatever works – nonopolarity Aug 31 '12 at 07:08
1

UIAutoresizingFlexibleWidth means that the view's width will expand and shrink when its superview's width expands and shrinks. UIAutoresizingFlexibleHeight means the same thing for height. Adding these is equivalent to turning on "springs" in Interface Builder. I think that if there are no "struts" set, when the superview doubles in width, the view will double in width as well.

The strut settings are:

  • UIViewAutoresizingFlexibleRightMargin
  • UIViewAutoresizingFlexibleLeftMargin
  • UIViewAutoresizingFlexibleTopMargin
  • UIViewAutoresizingFlexibleBottomMargin

If UIViewAutoresizingFlexibleRightMargin is NOT set, the right strut is turned on. This means that the space between the right side of your view and the right side of its superview will not change when the view expands. The same concept holds for all the other margins.

There is as good discussion here: https://stackoverflow.com/a/10470469/472344.

I think you are confused by the self.view.bounds that you are getting. This is the bounds of the view before rotation, as jrturton pointed out the height is 1004 because 20 pixels are subtracted for the status bar. I don't know why after rotation the width and height haven't updated (I'm assuming your rotation happens before loading the view, otherwise the printed out bounds are exactly what you should expect), but I have noticed this as well after rotation. I have seen some discussion on Stackoverflow about this, but I can't find it at the moment.

My guess is that as jrturton said, when the view is loaded, it uses the bounds set in the xib (or the storyboard), and the resizing happens after viewDidLoad. Maybe try printing out the bounds of self.frame.view in viewDidAppear, as the bounds should have changed at that point.

To address the behaviour of the auto resizing mask settings again, understand that these do NOTHING unless the view's superview changes size. The auto resizing mask settings will tell your view how to automatically resize when its superview changes size. If you want your table view to have the same size as self.view always (such as after rotation, or zooming), you need to set it exactly as you have done:

table = [[UITableView alloc] initWithFrame:self.view.bounds];
table.autoresizingMask = UIViewAutoresizingFlexibleWidth | 
                         UIViewAutoresizingFlexibleHeight;
[self.view addSubview:table];
Community
  • 1
  • 1
Darren
  • 10,091
  • 18
  • 65
  • 108
0

1004 is correct - the status bar is 20px. Your first code snippet is fine.

Note that in viewDidLoad your view's orientation will still be in portrait - hence the numbers you are seeing. The resize happens afterwards. Using the bounds rectangle of the main view as the frame of a subview will always let the subview fill the whole view.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • I am suspecting that the 768, 1004 is to mean "fill the whole view", and the resize will honor and scale accordingly to "fill the whole view"... – nonopolarity Aug 31 '12 at 07:11
  • 1
    No, if you set an explicit frame size, that will be the frame size. It will be resized as the superview's bounds changes (which happens on rotation). There is no "interpretation" of the frame to mean full screen. – jrturton Aug 31 '12 at 08:34