web-dev-qa-db-ja.com

iOS 6でUIViewControllerを強制的に縦向きにする方法

ShouldAutorotateToInterfaceOrientationはiOS 6で非推奨になり、特定のビューをポートレートのみに強制するために使用しましたが、iOS 6でこれを行う正しい方法は何ですか?これはアプリの1つの領域のみで、他のすべてのビューは回転できます。

85
Neal

すべてのNavigation Controllerがトップビューコントローラーを尊重するようにしたい場合は、カテゴリーを使用して、クラス名を変更する必要がありません。

@implementation UINavigationController (Rotation_IOS6)

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

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

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

@end

いくつかのコメントが指摘しているように、これは問題の簡単な修正です。より良い解決策は、サブクラスUINavigationControllerであり、これらのメソッドをそこに配置します。サブクラスは、6と7のサポートにも役立ちます。

117
Anthony

IOS6の最適な方法は、レイウェンダリッヒチームによる「チュートリアルによるiOS6」に具体的に記載されています- http://www.raywenderlich.com/ ほとんどの場合、UINavigationControllerをサブクラス化するよりも優れています。

初期ビューコントローラーとしてUINavigationControllerセットを含むストーリーボードでiOS6を使用しています。

//AppDelegate.m-このメソッドは、残念ながらiOS6以前では使用できません

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;

if(self.window.rootViewController){
    UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
    orientations = [presentedViewController supportedInterfaceOrientations];
}

return orientations;
}

//MyViewController.m-各UIViewControllerに対してサポートしたい方向を返します

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}
63
Phil

この回答は、OPの投稿のコメントで尋ねられた質問に関連しています。

ビューを強制的に特定の方向に表示するには、viewWillAppearに次のように入力します。

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
    UIViewController *c = [[UIViewController alloc]init];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}

ちょっとしたハックですが、これにより、前のコントローラーが横長であったとしても、UIViewControllerがポートレートで表示されます。

iOS7の更新

上記のメソッドは非推奨になったため、iOS 7では次を使用します。

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
     UIViewController *c = [[UIViewController alloc]init];
     [c.view setBackgroundColor:[UIColor redColor]];
     [self.navigationController presentViewController:c animated:NO completion:^{
            [self.navigationController dismissViewControllerAnimated:YES completion:^{
            }];
     }];
}

興味深いことに、執筆時点では、eitherpresentまたはdismissをアニメーション化する必要があります。どちらでもない場合は、白い画面が表示されます。なぜこれが機能するのかわかりませんが、機能します!視覚効果は、アニメーション化されるものによって異なります。

39
Craig Watkinson

そのため、ポートレートのみのモーダルビューを表示すると、同じ問題が発生しました。通常、UINavigationControllerを作成し、viewControllerrootViewControllerとして設定し、UINavigationControllerをモーダルビューとして表示します。しかし、iOS 6では、viewControllerは、navigationControllerにサポートされているインターフェイスの向きを要求するようになりました(デフォルトでは、iPadのすべてで、iPhoneの場合は上下逆になっています)。

ソリューションUINavigationControllerをサブクラス化し、自動回転メソッドをオーバーライドする必要がありました。ラメの種類。

- (BOOL)shouldAutorotate {
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
// pre-iOS 6 support 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
36
rocky

IOS 5

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

}

IOS 6

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{

    //    UIInterfaceOrientationMaskLandscape;
    //    24
    //
    //    UIInterfaceOrientationMaskLandscapeLeft;
    //    16
    //
    //    UIInterfaceOrientationMaskLandscapeRight;
    //    8
    //
    //    UIInterfaceOrientationMaskPortrait;
    //    2

    //    return UIInterfaceOrientationMaskPortrait; 
    //    or
          return 2;
}
15

UIViewControllerの回転メソッドはカテゴリ自体で宣言されているため、別のカテゴリでオーバーライドすると未定義の動作が発生するため、@ apratoの回答には同意しません。 UINavigationController(またはUITabBarController)サブクラスでオーバーライドする方が安全です

また、これは、横向きビューから縦向きのみVCまたはその逆にプッシュ/プレゼン/ポップするシナリオをカバーしません。この困難な問題を解決するには(Appleが決して対処しません)、次のことを行う必要があります。

iOS <= 4およびiOS> = 6:の場合

UIViewController *vc = [[UIViewController alloc]init];
[self presentModalViewController:vc animated:NO];
[self dismissModalViewControllerAnimated:NO];
[vc release];

iOS 5の場合

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];

これらは本当に、すべてのshouldAutorotate、supportedInterfaceOrientationsなどをUIKitに再評価させます。

10
Rafael Nobre

https://stackoverflow.com/a/13982508/2516436https://stackoverflow.com/a/17578272/2516436 を組み合わせた非常に良いアプローチがあります

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;


    if(self.window.rootViewController){
        UIViewController *presentedViewController = [self topViewControllerWithRootViewController:self.window.rootViewController];
        orientations = [presentedViewController supportedInterfaceOrientations];
    }

    return orientations;
}

- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
}

各UIViewControllerでサポートする方向を返します

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}
3
Alex Guerra

ここで退屈することはありませんが、あなたのサブクラスを共有してくれませんか?ありがとうございました。

編集:まあ、私はついにそれをやった、サブクラスはとても簡単にできた。 navigationControllerAppDelegateをデフォルトのUINavigationControllerSubclassの代わりにUINavigationControllerとして宣言し、サブクラスを次のように変更する必要がありました。

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

viewDidLoadを呼び出すことで、回転するかどうかの任意のビューを設定できます

_navController = (UINavigationController *)self.navigationController;
[_navController setShouldRotate : YES / NO]

このTweakが他の人にも役立つことを願っています、あなたのヒントをありがとう!

ヒント:活用する

- (NSUInteger)supportedInterfaceOrientations

view Controllerで使用しますので、ポートレートで望みの景色を横向きにしたり、その逆を行ったりすることはありません。

1
Roland

UISplitViewControllerとUISegmentedControllerを使用する比較的複雑なユニバーサルアプリがあり、presentViewControllerを使用してランドスケープで表示する必要があるビューがいくつかあります。上記の方法を使用して、iPhone ios 5および6を許容範囲内で動作させることができましたが、何らかの理由でiPadが単にLandscapeとして表示することを拒否しました。最後に、デバイスとiOS 5および6の両方で機能する簡単なソリューション(数時間の読み取りと試行錯誤の後に実装された)を見つけました。

ステップ1)コントローラーで、必要な方向を指定します(上記のように多かれ少なかれ)

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

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    NSInteger mask = UIInterfaceOrientationMaskLandscape;
    return mask;

}

ステップ2)シンプルなUINavigationControllerサブクラスを作成し、次のメソッドを実装します

-(BOOL)shouldAutorotate {
        return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
        return UIInterfaceOrientationMaskLandscape;
}

ステップ3)viewControllerを提示する

vc = [[MyViewController alloc]init];
MyLandscapeNavigationController *myNavigationController = [[MyLandscapeNavigationController alloc] initWithRootViewController:vc];
[self myNavigationController animated:YES completion:nil];

これが誰かに役立つことを願っています。

1
user216661

UINavigationControllerおよびUITabBarControllerクラス内のVCを許可するためにサブクラスまたはカテゴリを使用した回答はうまく機能します。横向きのTab Bar Controllerから縦向きのみのモーダルを起動できませんでした。これを行う必要がある場合は、アニメーション化されていないモーダルビューを表示および非表示にするトリックを使用しますが、viewDidAppearメソッドで行います。 viewDidLoadまたはviewWillAppearでは動作しませんでした。

それとは別に、上記のソリューションは正常に動作します。

0
Peter

Monotouchの場合、次のようにできます。

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
    {
    return UIInterfaceOrientationMask.LandscapeRight;
}

public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation()
    {
    return UIInterfaceOrientation.LandscapeRight;
}
0
TJS

私はそれを自分でテストしませんでしたが、ドキュメントには、これらのメソッドをオーバーライドできるようになったことが記載されています:supportedInterfaceOrientationsおよびpreferredInterfaceOrientationForPresentation

おそらく、これらのメソッドで必要な方向のみを設定することで、目的を達成できます。

0
J_D

私は多くの答えを見ますが、特定のアイデアと方向についての答えは得られませんが、リンクが方向をよく理解し、ios6の強制回転を削除するのを見ます。

http://www.disalvotech.com/blog/app-development/iphone/ios-6-rotation-solution/

私はそれが完全に役立つと思います。

0
PeterParker