xcode 在 iOS 6 上使用 Objective-C 强制横向方向

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13872244/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 02:19:12  来源:igfitidea点击:

Force Landscape Orientation on iOS 6 in Objective-C

objective-cxcodeuinavigationcontrollerlandscape

提问by jaytrixz

I have a master view controller that's inside a UINavigationController. In that master view controller, I have a button that pushes a detail view controller that has a UIWebView inside of it. I want this detail view controller to be on landscape mode when it's loaded. Going back to the master view controller, it forcibly goes back again to portrait mode. I'm running iOS 6 on this.

我有一个主视图控制器,它位于 UINavigationController 中。在那个主视图控制器中,我有一个按钮可以推送一个内部有 UIWebView 的细节视图控制器。我希望这个细节视图控制器在加载时处于横向模式。回到主视图控制器,它又强行回到纵向模式。我正在运行 iOS 6。

I have seen the other similar questions but it's not working on my end. I have created a LandscapeViewController that's a subclass of UIViewController where I have written these methods:

我看过其他类似的问题,但对我来说不起作用。我创建了一个 LandscapeViewController,它是 UIViewController 的子类,我在其中编写了以下方法:

#pragma mark - Orientation Methods
- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscape;
}

- (BOOL)shouldAutorotate
{
    return YES;
}

This is my code when I push the detail view controller:

这是我推送详细信息视图控制器时的代码:

DetailViewController *detailVC = [[DetailViewController alloc]
                                      initWithNibName:@"DetailViewController"
                                      bundle:nil];

    [self.navigationController pushViewController:detailVC
                                         animated:YES];

I'm thinking on where to subclass my LandscapeViewController on the code above to make it work or on how to properly subclass and push my detail view controller. I can also present my detail view controller modally if it's not possible for the navigation controller to push my detail view controller from portrait to landscape. Where am I doing it wrong?

我正在考虑在上面的代码上在哪里对我的 LandscapeViewController 进行子类化以使其工作,或者如何正确地子类化并推送我的详细信息视图控制器。如果导航控制器不可能将我的细节视图控制器从纵向推到横向,我也可以模态地呈现我的细节视图控制器。我哪里做错了?

回答by fdiaz

Considering: View A: Portrait only - View B: Landscape only

考虑:视图 A:仅纵向 - 视图 B:仅横向

I couldn't do it in the navigation controller. Instead what I did was to open a modal view from view A to view B and force a new navigation controller into this view.

我无法在导航控制器中做到这一点。相反,我所做的是打开一个从视图 A 到视图 B 的模态视图,并强制一个新的导航控制器进入这个视图。

This is working for me in iOS5+.

这在 iOS5+ 中对我有用。

You need to create a category for the navigation controller like this:

您需要为导航控制器创建一个类别,如下所示:

UINavigationController+Rotation_IOS6.h

UINavigationController+Rotation_IOS6.h

#import <UIKit/UIKit.h> 

@interface UINavigationController (Rotation_IOS6)

- (BOOL)shouldAutorotate;
- (NSUInteger)supportedInterfaceOrientations;
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;

@end

UINavigationController+Rotation_IOS6.h

UINavigationController+Rotation_IOS6.h

#import "UINavigationController+Rotation_IOS6.h"

@implementation UINavigationController (Rotation_IOS6)

- (BOOL)shouldAutorotate
{
    return [self.topViewController shouldAutorotate];
}

- (NSUInteger)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [self.topViewController preferredInterfaceOrientationForPresentation];
}

@end

In AppDelegate.madd:

AppDelegate.m添加:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    return UIInterfaceOrientationMaskAll;
}

Then in View A:

然后在视图 A 中

- (BOOL)shouldAutorotate {
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}

also in View A to open View Bdo this:

同样在视图 A 中打开视图 B执行以下操作:

ViewB *vc = [[ViewB alloc] initWithNibName:@"ViewB" bundle:nil];

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc];

[self presentViewController:navigationController animated:YES completion:nil];

And, finally, in View B

最后,在视图 B

- (BOOL)shouldAutorotate {
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationLandscapeRight;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

回答by Hot Licks

They kinda screwed the pooch in iOS 6 with regard to this. Here's what I've figured out so far:

在这方面,他们有点搞砸了 iOS 6 中的狗。这是我到目前为止想出来的:

First off, Apple added the "Supported Interface Orientations" buttons with Xcode 4.5. This corresponds to the "Supported interface orientations" attribute in _info.plist. These buttons must be toggled to the correct choices before any of the rest will work. (If the buttons seem to refuse to toggle it's likely because the info.plist is locked by CVS or some other process.)

首先,Apple 在 Xcode 4.5 中添加了“支持的界面方向”按钮。这对应于 _info.plist 中的“支持的界面方向”属性。必须将这些按钮切换到正确的选项,其余按钮才能起作用。(如果按钮似乎拒绝切换,可能是因为 info.plist 被 CVS 或其他一些进程锁定了。)

Next, the property .window.rootViewController must be set, and must point to the "bottom" view controller in the stack. Generally this will be either a navigation controller or a tab controller.

接下来,必须设置属性 .window.rootViewController,并且必须指向堆栈中的“底部”视图控制器。通常,这将是导航控制器或选项卡控制器。

If the desire is to disable all rotation, this can be done using the buttons, or one can implement, in the "bottom" view controller, the "shouldAutorotate" method and have it return NO. (If the method is omitted then the default is YES.)

如果希望禁用所有旋转,这可以使用按钮来完成,或者可以在“底部”视图控制器中实现“shouldAutorotate”方法并让它返回 NO。(如果省略该方法,则默认值为 YES。)

In spite of having autorotation disabled with shouldAutorotate, if there is a MPMoviePlayerViewController being displayed, that will autorotate. Only toggling the supported interface orientation buttons appears to prevent this.

尽管使用 shouldAutorotate 禁用了自动旋转,但如果显示 MPMoviePlayerViewController,它将自动旋转。只有切换支持的界面方向按钮才会出现这种情况。

If one wants to conditionally autorotate other view controllers it gets messier. Basically, your "bottom" view controller must implement the supportedInterfaceOrientations method and return, based on the current topViewController, the appropriate bit mask. This can be done with a routine that queries the topViewController's old "shouldAutorotateToInterfaceOrientation" method, but it's a bit ugly. And even though this scheme doesn't require modifying the rotating view controller's code, you DO need to modify the VC just "below" the rotated one to implement "supportedInterfaceOrientation", or else that view will be rotated on return. (At least this is a simple copy/paste.) No one seems to have come up with a better, more general scheme, though.

如果想要有条件地自动旋转其他视图控制器,它会变得更加混乱。基本上,您的“底部”视图控制器必须实现 supportedInterfaceOrientations 方法并根据当前的 topViewController 返回适当的位掩码。这可以通过查询 topViewController 旧的“shouldAutorotateToInterfaceOrientation”方法的例程来完成,但它有点难看。即使此方案不需要修改旋转视图控制器的代码,您也需要修改旋转视图“下方”的 VC 以实现“supportedInterfaceOrientation”,否则该视图将在返回时旋转。(至少这是一个简单的复制/粘贴。)不过,似乎没有人想出更好、更通用的方案。