Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This is a pain and it's still true in iOS 4.2 for iPads. The way I solved this is to subclass the <code>UIView</code> associated with the <code>UIViewController</code>. I did this in interface builder but I suppose one could also do this in code somehow. In interface builder select the UIView in the <code>UIViewController</code> then hit the (i) icon in the upper right of the Inspector window. Under class identity hit the popup and chose the UIView subclass below.</p> <p>The approach is that this UIView subclass overrides the layoutSubviews method, finds the next <code>UIViewController</code>, determines if it implements a reactToLayout method (which is a method that you have to implement in the <code>UIViewController</code> subclass for the view controller of this view). If the reactToLayout method exists in the first <code>UIViewController</code> found, it is invoked.</p> <p>The reactToLayout method in the view controller then does whatever one needs to do which it will be able to do successfully since the view's frame is set up properly by this time (unlike in <code>ViewDidLoad</code>, <code>viewWillAppear</code>, or even <code>viewDidAppear</code>). I have a method that I call anytime the orientation or frame changes. It's a pain but I store the last frame laid out and last orientation laid out in internal variables of the view controller. The internal layout for new orientation or frame change method compares these to the view's current frame and requested or current orientation so that it doesn't unnecessarily layout stuff over and over.</p> <p>Here's the code:</p> <p>UILayoutSubviewsView.h</p> <pre><code>#import &lt;UIKit/UIKit.h&gt; @interface UILayoutSubviewsView : UIView { } @end </code></pre> <p>UILayoutSubviewsView.m</p> <pre><code>#import "UILayoutSubviewsView.h" // Create this to avoid a warning that this method does not exist for UIViewControllers // this is OK since we check to see that it does exist before invoking it @interface UIViewController(UndocumentedMethodForUIViewController) -(void) reactToLayout; @end @implementation UILayoutSubviewsView // Pass this up to our view controller if it supports the reactToLayout method // (this is the whole reason for the class) -(void) layoutSubviews { [super layoutSubviews]; // Look for the first next responder that is a UIViewController UIViewController *ourViewController = nil; id myNextResponder = [self nextResponder]; while (myNextResponder != nil &amp;&amp; ourViewController == nil) { if ([myNextResponder isKindOfClass:[UIViewController class]]) { ourViewController = myNextResponder; } else { myNextResponder = [myNextResponder nextResponder]; } } // If we got a view controller, then see if it supports the reactToLayout method if (ourViewController != nil) { if ([ourViewController respondsToSelector:@selector(reactToLayout)]) { // Invoke the view controller's reactToLayout method [ourViewController reactToLayout]; } } } @end </code></pre> <p>YourViewController.h</p> <pre><code>#import &lt;UIKit/UIKit.h&gt; @interface YourViewController : UIViewController { CGRect lastLayedOutFrame; UIInterfaceOrientation lastLayedOutOrientation; } #pragma mark - #pragma mark Instance Methods -(id) init; -(void) reactToLayout; @end </code></pre> <p>YourViewController.m</p> <pre><code>#import "YourViewController.m" #pragma mark Private Interface Category @interface YourViewController() -(void) setViewForCurrentFrameAndRequestedOrientation:(UIInterfaceOrientation) interfaceOrientation; @end @implementation YourPadViewController -(id) init { // First our super then set ourselves up if (self = [super initWithNibName:@"YourViewController" bundle:nil]) { // Initialize some basic stuff lastLayedOutFrame = CGRectZero; lastLayedOutOrientation = UIDeviceOrientationUnknown; } return self; } -(void) viewWillAppear:(BOOL) animated { [super viewWillAppear:animated]; // Make sure we're showing the right stuff in the right place [self setViewForCurrentFrameAndRequestedOrientation:UIDeviceOrientationUnknown]; } -(void) viewDidAppear:(BOOL) animated { [super viewDidAppear:animated]; // Make sure we're showing the right stuff in the right place [self setViewForCurrentFrameAndRequestedOrientation:UIDeviceOrientationUnknown]; } -(void) reactToLayout { // Make sure we're showing the right stuff in the right place [self setViewForCurrentFrameAndRequestedOrientation:UIDeviceOrientationUnknown]; } #pragma mark - #pragma mark Rotation Support -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { return YES; } // This is called right before the actual rotation -(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation duration:(NSTimeInterval) duration { [super willAnimateRotationToInterfaceOrientation:interfaceOrientation duration:duration]; // Make sure we're showing the right stuff in the right place [self setViewForCurrentFrameAndRequestedOrientation:interfaceOrientation]; } // Make the necessary adjustments for the different view orientations -(void) setViewForCurrentFrameAndRequestedOrientation:(UIInterfaceOrientation) interfaceOrientation { // Set up the requested orientation (need this to handle the Unknown case) UIInterfaceOrientation requestedOrientation; if (interfaceOrientation != UIDeviceOrientationUnknown) { requestedOrientation = interfaceOrientation; } else { requestedOrientation = [[UIDevice currentDevice] orientation]; } // See if we have anything to do if (!(CGRectEqualToRect(self.view.frame, lastLayedOutFrame) &amp;&amp; lastLayedOutOrientation == requestedOrientation)) { // Do whatever needs to be done // Record our last layed out frame and orientation lastLayedOutFrame = self.view.frame; lastLayedOutOrientation = requestedOrientation; } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload