Это боль, и это все еще верно в iOS 4.2 для iPad. Я решил, что это подкласс UIView
, связанный с UIViewController
. Я сделал это в конструкторе интерфейсов, но я полагаю, что кто-то мог также сделать это в коде. В конструкторе интерфейса выберите UIView в UIViewController
, затем нажмите значок (i) в верхнем правом углу окна инспектора. Под идентификатором класса нажмите всплывающее окно и выберите подкласс UIView ниже.
Подход заключается в том, что этот подкласс UIView переопределяет метод layoutSubviews, находит следующий UIViewController
, определяет, реализует ли он методactToLayout (который необходимо реализовать в подклассе UIViewController
для контроллера представления этот вид). Если методactToLayout существует в первом найденном UIViewController
, он вызывается.
Затем методactToLayout в контроллере представления выполняет все, что ему нужно, что он сможет успешно выполнить, поскольку к этому времени кадр представления настроен правильно (в отличие от ViewDidLoad
, viewWillAppear
или даже *). 1013 *). У меня есть метод, который я вызываю каждый раз, когда меняется ориентация или рамка. Это неприятно, но я сохраняю последний развернутый кадр и последнюю ориентацию во внутренних переменных контроллера представления. Внутренний макет для новой ориентации или метода смены кадров сравнивает их с текущим кадром и запрошенной или текущей ориентацией представления, чтобы он не создавал ненужные макеты снова и снова.
Вот код:
UILayoutSubviewsView.h
#import <UIKit/UIKit.h>
@interface UILayoutSubviewsView : UIView {
}
@end
UILayoutSubviewsView.m
#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 && 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
YourViewController.h
#import <UIKit/UIKit.h>
@interface YourViewController : UIViewController {
CGRect lastLayedOutFrame;
UIInterfaceOrientation lastLayedOutOrientation;
}
#pragma mark -
#pragma mark Instance Methods
-(id) init;
-(void) reactToLayout;
@end
YourViewController.m
#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) && lastLayedOutOrientation == requestedOrientation)) {
// Do whatever needs to be done
// Record our last layed out frame and orientation
lastLayedOutFrame = self.view.frame;
lastLayedOutOrientation = requestedOrientation;
}
}