如何以编程方式在iOS7中设置设备方向?

我正在使用一个iPad应用程序,使用自动布局,如果用户启用某种模式(“抬头”模式),我只想支持肖像(或肖像倒置)方向,此外,如果设备在风景,我想自动切换到肖像模式。

在顶视图控制器中,我有以下几点:

- (NSUInteger) supportedInterfaceOrientations { if (self.modeHeadsUp) { return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown; } else { return UIInterfaceOrientationMaskAll; } } - (BOOL) shouldAutorotate { return TRUE; } 

根据我在别处看到的答案,答案似乎是我应该使用“应用程序setStatusBarOrientation”。 因此,在用户select“抬头”模式的方法中,我包括:

  UIApplication *application = [UIApplication sharedApplication]; [application setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES]; 

但是,这似乎并没有做任何事情。 虽然我可以物理移动设备,让它旋转成肖像,但它不会自动执行。

实际上,在运行上面的代码之后,在横向模式下尝试以编程方式设置方向时,使用以下代码查询应用程序“statusBarOrientation”时,横向将保持为“4”:

 UIApplication *application = [UIApplication sharedApplication]; int orientation = [application statusBarOrientation]; self.movesTextView.text = [NSString stringWithFormat:@"ORIENTATION %d", orientation]; 

它似乎也许自动布局没有被setStatusBarOrientation触发,所以我试图添加此代码后,没有任何效果:

  [super updateViewConstraints]; [self.view updateConstraints]; 

我意识到苹果希望将设备方向留在用户手中。 但是,我不希望在“抬头”模式下支持横向模式。

我是否错过了能够强制改变方向的东西?

对于iOS 7和8:

Objective-C的:

 NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 

迅速:

 let value = UIInterfaceOrientation.LandscapeLeft.rawValue UIDevice.currentDevice().setValue(value, forKey: "orientation") 

我在- viewDidAppear:

用这个。 定位问题的完美解决scheme

 [[UIDevice currentDevice] setValue: [NSNumber numberWithInteger: UIInterfaceOrientationPortrait] forKey:@"orientation"]; 

当条件发生变化时,您需要调用attemptRotationToDeviceOrientation (UIViewController)以使系统调用supportedInterfaceOrientations

这适用于Xcode 6&5。

 - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return (UIInterfaceOrientationMaskPortrait); } 
 NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 

确实有效,但是你必须在视图控制器中返回YESAutorotate

 - (BOOL)shouldAutorotate { return self.shouldAutoRotate; } 

但是,如果你这样做,你的VC将自动旋转,如果用户旋转设备…所以我把它改为:

 @property (nonatomic, assign) BOOL shouldAutoRotate; - (BOOL)shouldAutorotate { return self.shouldAutoRotate; } 

我打电话

 - (void)swithInterfaceOrientation:(UIInterfaceOrientation)orientation { self.rootVC.shouldAutoRotate = YES; NSNumber *value = [NSNumber numberWithInt: orientation]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; } 

用button单击强制一个新的方向。 要设置回应shouldAutoRotate为NO,我添加到我的rootVC

 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { self.shouldAutoRotate = NO; } 

PS:这个解决方法也适用于所有模拟器。

对我来说唯一的方法就是展示虚拟模态视图控制器。

 UIViewController* dummyVC = [[UIViewController alloc] init]; dummyVC.view = [[UIView alloc] init]; [self presentModalViewController:dummyVC animated:NO]; [self dismissModalViewControllerAnimated:NO]; 

模态视图控制器closures时,VC将被要求更新界面方向。

好奇的是,UINavigationController在按下/popup具有不同支持的界面方向的子视图控制器(在iOS 6.1,7.0上testing)时完成了这一操作。

如果要将应用程序的主视图locking为纵向,但希望在横向中打开popup视图,并且您正在使用tabBarController作为rootViewController,则可以在AppDelegate上使用此代码。

AppDelegate.h

 @interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate> @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) UITabBarController *tabBarController; @end 

AppDelegate.m

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Create a tab bar and set it as root view for the application self.tabBarController = [[UITabBarController alloc] init]; self.tabBarController.delegate = self; self.window.rootViewController = self.tabBarController; ... } - (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController { return UIInterfaceOrientationMaskPortrait; } - (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController { return UIInterfaceOrientationPortrait; } 

它工作得很好。

在viewController中,您想要在横向上呈现,您只需使用以下内容:

 - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; } - (BOOL)shouldAutorotate { return YES; } 
  1. 将此语句添加到AppDelegate.h

     //whether to allow cross screen marker @property (nonatomic, assign) allowRotation BOOL; 
  2. 将这部分代码写入AppDelegate.m

     - (UIInterfaceOrientationMask) application: (UIApplication *) supportedInterfaceOrientationsForWindow: application (UIWindow *) window { If (self.allowRotation) { UIInterfaceOrientationMaskAll return; } UIInterfaceOrientationMaskPortrait return; } 
  3. 更改委托应用程序的allowRotation属性

这个解决scheme可以让你强制一定的接口方向,暂时覆盖UIDevice.current.orientation的值,然后让系统旋转接口来匹配设备的旋转:

重要提示:这是一个黑客攻击,可能随时停止工作

在您的应用的根视图控制器中添加以下内容:

 class RootViewController : UIViewController { private var _interfaceOrientation: UIInterfaceOrientation = .portrait override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask(from: _interfaceOrientation) } override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { return _interfaceOrientation } override func viewDidLoad() { super.viewDidLoad() // Register for notifications NotificationCenter.default.addObserver(self, selector: #selector(RootViewController.handleInterfaceOrientationChangeRequestedNotification(_:)), name: .interfaceOrientationChangeRequested, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } func handleInterfaceOrientationChangeRequestedNotification(_ notification: Notification) { guard let interfaceOrientation = notification.object as? UIInterfaceOrientation else { return } _interfaceOrientation = interfaceOrientation // Set device orientation // Important: // • Passing a UIDeviceOrientation here doesn't work, but passing a UIInterfaceOrientation does // • This is a hack, and could stop working at any moment UIDevice.current.setValue(interfaceOrientation.rawValue, forKey: "orientation") // Rotate the interface to the device orientation we just set UIViewController.attemptRotationToDeviceOrientation() } } private extension UIInterfaceOrientationMask { init(from interfaceOrientation: UIInterfaceOrientation) { switch interfaceOrientation { case .portrait: self = .portrait case .landscapeLeft: self = .landscapeLeft case .landscapeRight: self = .landscapeRight case .portraitUpsideDown: self = .portraitUpsideDown case .unknown: self = .portrait } } } extension Notification.Name { static let interfaceOrientationChangeRequested = Notification.Name(rawValue: "interfaceOrientationChangeRequested") } 

确保在“部署信息”下检查所有界面方向:

界面方向

在需要的地方请求界面方向更改:

 NotificationCenter.default.post(name: .interfaceOrientationChangeRequested, object: UIInterfaceOrientation.landscapeRight) 

基本的UINavigationController应该有下面的callback,以便子项可以决定他们想要的方向。

 -(NSUInteger)supportedInterfaceOrientations { UIViewController *topVC = self.topViewController; return topVC.supportedInterfaceOrientations; } -(BOOL)shouldAutorotate { UIViewController *topVC = self.topViewController; return [topVC shouldAutorotate]; } 

如果你只想要肖像模式,在iOS 9(Xcode 7)中,你可以:

  • 去Info.plist
  • select“支持的界面方向”项目
  • 删除“风景(左主页button)”和“风景(右主页button)”

在这里输入图像说明

我和你有类似的问题。 我需要为某些屏幕locking设备方向(如“login”),并允许其他人旋转。

经过一些改变,下面的一些答案我做到了:

  • 启用项目的Info.plist中的所有方向。

在这里输入图像说明

  • 在那些需要设备不旋转的ViewController中禁用方向,就像在我的情况下的login屏幕一样。 我需要重写此VC中的shouldAutorotate方法:

-(BOOL)shouldAutorotate{ return NO; }

希望这会为你工作。

如果你有一个UIViewController应该保持肖像模式,只需添加这个覆盖,你就全部设置了。

 override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { return UIInterfaceOrientationMask.Portrait } 

最好的部分是这个视图显示时没有animation,它已经处于正确的方向。

这里是一个完整的工作例子iOS 7,8,9,10如何改变应用程序的方向,以目前的相反

Objective-C的

 - (void)flipOrientation { NSNumber *value; UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation]; if(UIInterfaceOrientationIsPortrait(currentOrientation)) { if(currentOrientation == UIInterfaceOrientationPortrait) { value = [NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown]; } else //if(currentOrientation == UIInterfaceOrientationPortraitUpsideDown) { value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait]; } } else { if(currentOrientation == UIInterfaceOrientationLandscapeRight) { value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; } else //if(currentOrientation == UIInterfaceOrientationLandscapeLeft) { value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]; } } [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; [UIViewController attemptRotationToDeviceOrientation]; } 

Swift 3

 func flipOrientation() -> Void { let currentOrientation : UIInterfaceOrientation = UIApplication.shared.statusBarOrientation var value : Int = 0; if(UIInterfaceOrientationIsPortrait(currentOrientation)) { if(currentOrientation == UIInterfaceOrientation.portrait) { value = UIInterfaceOrientation.portraitUpsideDown.rawValue } else //if(currentOrientation == UIInterfaceOrientation.portraitUpsideDown) { value = UIInterfaceOrientation.portrait.rawValue } } else { if(currentOrientation == UIInterfaceOrientation.landscapeRight) { value = UIInterfaceOrientation.landscapeLeft.rawValue } else //if(currentOrientation == UIInterfaceOrientation.landscapeLeft) { value = UIInterfaceOrientation.landscapeRight.rawValue } } UIDevice.current.setValue(value, forKey: "orientation") UIViewController.attemptRotationToDeviceOrientation() } 

试试这个和你的代码一起。

 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

一旦用户select任何选项,然后调用此方法,因为用户可以处于横向模式,然后他可以在同一个视图控制器中只设置肖像模式,所以自动查看应该移动到肖像模式,所以在该button,

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