I’ve got a main View Controller that has a subview of UIScrollView and another 2 UIViewControllers (each with nibs UIView and buttons). The UIViewControllers’ UIView are added into UIScrollView using addSubView method. And I’d like to put both UIViewControllers side by side.
I’ve got the following code but it doesn’t seem to work.
[self scrollView].pagingEnabled = YES;
[self scrollView].contentSize = CGSizeMake(768 * 2, 1024);
[[self scrollView] setDelegate:self];
CGRect frame1;
frame1.origin.x = 0;
frame1.origin.y = 0;
frame1.size = CGSizeMake(768, 1024);
// Model one
oneView = [[OneViewController alloc] initWithNibName:@"OneViewController" bundle:nil];
//oneView.view.frame = frame1;
[self.scrollView addSubview:oneView.view];
oneView.view.frame = frame1;
// Model two
CGRect frame2;
frame2.origin.x = 768;
frame2.origin.y = 0;
frame2.size = CGSizeMake(768, 1024);
twoView = [[TwoViewController alloc] initWithNibName:@"TwoViewController" bundle:nil];
//twoView.view.frame = frame2;
[self.scrollView addSubview:twoView.view];
twoView.view.frame = frame2;
Why does oneView and twoView inside UIScrollView are in the same place when I’ve set their frame.origin.x? twoView seems to be on top of oneView where it should be side by side? Any idea where I am doing it wrong? Thanks!
Update: Here’s my full project code on github: http://bit.ly/PLe1Le
The reason why this started happening is that any
UIViewinstance that is the value of aUIViewController‘sviewproperty will sometimes get a message to resize its view to that of its superviews.Specifically, the undocumented method
viewDidMoveToWindow:shouldAppearOrDisappear:will be called when a view controller’sviewis added to a window, as is happening at application launch in this instance. At this time, if the view controller’sviewinstance is the size of the main window or larger, it will be resized to the size of its superview.The original code took the two views that were loaded from the the .xibs and sized them to 768 * 1024, which is the size of the window. This happens before
-makeKeyAndVisibleis called on the window, which ends up triggering the resize. I used KVO in the app delegate to watch the frames get resized; here is a stack trace at the time of resize:We can verify that this happens because the content views are a
UIViewController‘s view instance by instantiating a view and adding it the scroll view at the same time. I added the following code to the end ofViewController‘sviewDidLoadimplementation:As well as changing the line assigning content size to:
This view does not get its frame set during
makeKeyAndVisibleand is in the correct place.To work around the issue, I’d recommend setting up the view hierarchy after the window has
-makeKeyAndVisiblecalled, possibly in a viewWillAppear (Not sure if that will have the same issue) or by otherwise structuring your code to delay the laying out of the scroll view. Alternatively, re-set the frames at a later time as an explicit undoing of this bug.I hope this helps explain what was happening and that the evidence I provide is clear and credible; it seems you already have a fix for your particular case but hopefully this answer stands as a general solution to frame misbehavior when
UIViewController‘s have their views laid out inside scroll views.