【问题标题】:Can I manually trigger whatever calls supportedInterfaceOrientations on my viewController?我可以在我的 viewController 上手动触发任何调用 supportedInterfaceOrientations 吗?
【发布时间】:2014-04-16 13:49:25
【问题描述】:
我有一个 UINavigationController 子类作为我的应用程序中的根 viewController。我将各种其他视图控制器推送到导航控制器的 viewControllers 堆栈中。
其中一些允许以任何方向显示,一些仅横向显示。
我使用了这个链接的信息:http://grokin.gs/blog/2012/11/16/orientationrespectfulnavigationcontroller/
这样当设备发生旋转时,导航控制器会正确报告顶视图控制器允许的方向。但是,当新的视图控制器被推入堆栈时,我似乎无法弄清楚如何触发自动旋转。
例如应用程序的根 vc 是我的 naviationViewController。它的初始顶部 vc 可以横向或纵向显示。假设设备是纵向的,现在我将另一个 vc 推到导航控制器上。这个新的vc只能横向显示。如果设备旋转了 360 度,那么会发生正确的事情,即 navController 将旋转限制为横向。但是,如果设备从不移动,则不会在 navController 上调用 supportInterfaceOrientations:,因此设备不知道 UI 应该自动旋转为横向。
那么——当旋转发生时,我可以触发 UIApplication 做任何事情吗?还是我错过了什么?
谢谢。
【问题讨论】:
标签:
cocoa-touch
uinavigationcontroller
screen-rotation
【解决方案1】:
因此,您似乎可以触发系统重新评估允许的设备方向。每当 viewController 以模态方式全屏呈现时都会发生这种情况。
因此,(这是一个令人讨厌的 hack,但它似乎有效)您可以要求根 VC 呈现一个只允许横向方向的 VC,然后在呈现后立即将其关闭。
例如见下面的代码:
- (void)viewDidAppear:(BOOL)animated
{
// Force an orientation update if we are not in landscape...
BOOL force = YES;
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationLandscapeLeft)
{
force = NO;
}
if (force)
{
PortraitOnlyViewController *newVC = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"forceLandscape"];
[self.navigationController presentViewController:newVC animated:NO completion:^(void){
NSLog(@"forcing VC has been presented.");
[self.navigationController dismissViewControllerAnimated:NO completion:^(void){
NSLog(@"forcing VC has been dismissed");
}];
}];
}
}
【解决方案2】:
我不得不修改 Diggory 的答案,因为我没有使用 UINavigationController,也使用 Swift。我在 iOS 8.3 上也遇到了以下错误:
Trying to dismiss the presentation controller while transitioning already. (<_UIFullscreenPresentationController
通过添加对 dispatch_get_main_queue 的调用解决了这个问题。
class ViewController: UIViewController {
var allowTurning = false
override func supportedInterfaceOrientations() -> Int {
if allowTurning {
return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
} else {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
}
@IBAction func doTurn(sender: UIButton) {
allowTurning = true
let fakeViewController = UIViewController()
presentViewController(fakeViewController, animated: false) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.dismissViewControllerAnimated(false, completion: {
NSLog("Done dismissing!")
})
})
}
}
}