iOS 5:第一次加载控制器时未调用 willRotateToInterfaceOrientation:duration

Posted

技术标签:

【中文标题】iOS 5:第一次加载控制器时未调用 willRotateToInterfaceOrientation:duration【英文标题】:iOS 5: willRotateToInterfaceOrientation:duration not called when first loading controller 【发布时间】:2011-11-04 22:35:28 【问题描述】:

我已经在我的代码中实现了这个方法来了解界面方向何时会发生变化:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

我依靠这个被调用来设置我的视图。在 ios 4 或 5 中,当方向改变时,它会被正确调用。

在 iOS 4 中,它也会在控制器首次加载时被调用(无论方向是否改变,它都会在开始时以正确的方向调用一次)。

问题是我注意到在 iOS 5 中这种情况不再发生。该方法在方向改变时被调用,但在控制器最初加载时不会被调用。这对我来说是个问题,因为我依靠它来根据方向设置初始视图位置。

任何想法为什么这种行为会改变?处理这个问题的最佳方法是什么?如果在 iOS 5 上,我应该检查 viewDidLoad 中的方向,然后手动调用 willRotate 和 didRotate 方法吗?这感觉有点像 hack。

感谢您提供的任何意见。

【问题讨论】:

【参考方案1】:

由于时间紧迫,我不得不解决这种奇怪的行为并手动调用 viewDidLoad 中的定位方法。这有点小技巧,但到目前为止它运行良好。

viewDidLoad 我添加了这个:

if ( SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.0") ) 
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    [self willRotateToInterfaceOrientation:interfaceOrientation duration:0.2f];

然后我将它添加到一个通用头文件中:

// iOS Version Checking
#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

我从答案 to this question on SO 中得到了 iOS 版本检查定义。

【讨论】:

【参考方案2】:

即使我遇到了类似的问题,也不得不在 tabbarcontroller 派生类中重写它以使其正常工作:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

    [_tabBarConroller willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

希望这会有所帮助!

【讨论】:

【参考方案3】:

我遇到了同样的问题,一直在拔头发。我终于找到了一个解决方案,但不幸的是,这仅适用于 iOS 5.0 +:

将以下代码放入自定义UIViewController 中的viewDidLoad 方法中:

double delayInSeconds = 0.1f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
    [UIViewController attemptRotationToDeviceOrientation];
);

这会将轮换更新推送到下一个运行循环。 attemptRotationToDeviceOrientation 是 iOS 5.0+ 调用。

【讨论】:

【参考方案4】:

从 iOS 5 及更高版本开始,您应该构建视图控制器层次结构(使用 -addChildViewController:)。然后子视图控制器开始再次调用 -willRotateToInterfaceOrientation:interfaceOrientation: 和其他接口相关的方法(因为父控制器会通知它们有关 UI 方向的变化)。

请不要使用任何“肮脏”的方法。

有用的文档: Apple docs about 'addChildViewController:'

【讨论】:

以上是关于iOS 5:第一次加载控制器时未调用 willRotateToInterfaceOrientation:duration的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 抖动问题:加载 viewController 时未调用 viewDidAppear

在 iOS 8 中重新加载时未调用 UICollectionview cellForItemAtIndexPath

重新加载表数据时未调用 CellForRowAtIndexPath

滚动时未调用 sizeForItemAt

从 UInavigationcontroller 呈现视图控制器后,不调用 ios 10 加载视图和 viewwillappear

未完全加载单元格时未调用 didSelectItemAtIndexPath