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


85

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

回答:


117

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

@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のサポートにも役立ちます。


3
これが動作することを確認できます。必要に応じて、「[self.viewControllerslastObject]」を「self.topViewController」に置き換えることもできます。
ウェイン劉

3
UITabBarControllerを使用している場合、このUINavigationControllerカテゴリは役に立ちません。あなたは...代わりにUITabBarControllerにカテゴリを作成する必要があります
Borut Tomazin

46
このソリューションの問題は、横向きのコントローラーをポップし、新しいトップコントローラーが縦向き(またはその逆)のみをサポートしている場合は機能しないことです。この場合、これらのコールバックは呼び出されず、方法がまだ見つかりません。新しいトップコントローラーを正しい方向に強制します。何か案は?
ロープ2012年

4
UINavigationControllerをサブクラス化し、window.rootControllerとして設定しました。3つのメソッドすべてを実装しました。デバイスの回転を変更するとうまく機能します。問題は、ビューコントローラーをポップするとそれらのメソッド(および回転に関連するものは何もない)が呼び出されることです
Lope

4
ランドスケープビューコントローラーからプッシュまたはポップを実行している場合、この強制UIViewControllerはランドスケープに変わります。ただし、縦向きに回転すると正常に機能し、横向きに変わることはありません。横からプッシュまたはポップするときの唯一の問題。助けてください
Tariq 2013年

63

iOS6のための最善の方法は、特にレイWenderlichチームによって「iOS6ことでチュートリアル」で注目される- http://www.raywenderlich.com/とサブクラス化するよりも優れているUINavigationControllerほとんどの場合。

UINavigationController初期のViewControllerとしてセットを含むストーリーボードで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;
}

1
これはiOS6に最適なソリューションです
Homam 2013年

2
@ Phil、iOS 6では問題なく動作します。ただし、横向きから縦向きに移行する場合など、場合によっては機能しません。なぜそれが起こるのか考えはありますか?
Kirti Nikam 2013年

1
非常に便利なソリューション。私にとって、最高です。
オスカーカステロン2013

1
iOS 7ベータ6での作業。私の場合、横向きから縦向きに移動するときに機能します。
マーティンバーガー

私はiOS6を使用していますが、これは機能しません。「UIViewController * presentedViewController」行で中断します。
マルセルマリノ

39

この回答は、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のアップデート

上記の方法は廃止されたため、iOS7では次を使用します。

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:^{
            }];
     }];
}

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


おかげで、私は数分の自由時間を見つけたらそれを試してみます
Lope

@RohanAgarwal宣伝どおりに機能します、ここで使用しています。ただし、承認された回答のコードも実装する必要があります。そうしないと、機能しません。
デニスマンシー2013年

2
正しい回転アニメーションでこれを同時に機能させる方法を誰かが理解しましたか?アニメーションなしでポートレートからランドスケープに切り替わるのを見るのは少し不快です。それは機能しますが、少しだけうまく機能することを望んでいます。
デニスマンシー2013年

@CraigWatkinsonストーリーボードでは機能していません。また、presentModalViewControllerとdismissModalViewControllerAnimatedは、iamがpresentVirecontrollerを使用している場合は非推奨になり、機能しません。助けてください
Kalpesh 2013

1
ios8の場合、dismissViewControllerAnimatedはクラッシュするだけです。[NWSAppDelegate sharedInstance] .window.rootViewController = nil;を呼び出すことがわかりました。[NWSAppDelegate sharedInstance] .window.rootViewController = previousRootControllerはうまく機能します。
Alexey 2014

36

そのため、縦向きのみのモーダルビューを表示するときに同じ問題が発生しました。通常は、を作成しUINavigationController、をviewControllerとして設定してからrootViewController、を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);
}

1
私のものでは動作しません。私はこのコードをすべての方向にグローバルに設定しました
phil88530 2012

2
supportedInterfaceOrientationsは、BOOLではなくNSUIntegerを返す必要があります。developer.apple.com/library/ios/#featuredarticles/…を
tomwhipple 2012年

それはうまくいきました、私にとってはタブバーコントローラーです、再び答えてくれてありがとう
otakuProgrammer 2012年

FWIW、私もこのルートに行かなければなりませんでした...他に何も機能しませんでした。ありがとう。
スティーブN

15

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;
}

優秀な!このスレッドの一番上に最大限にいる必要があります。それが問題を解決する最も簡単な方法だからです
Alex

@Roshan Jalgaonkar In ios 6それは私には機能しません私はホームボタンを押したままポートレートだけが必要ですこのUIOrientationを設定するにはどうすればよいですか....
Karthik

@Karthikこれを機能させるには、アプリのターゲットでサポートされているローテーションを有効にする必要があります。
アレハンドロイバン・

@ AlejandroIvánkthnx–
Karthik

10

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];

これらは本当にUIKitにすべてのshouldAutorotate、supportedInterfaceOrientationsなどを再評価するように強制します。


2
これらの最初のものは、iOSのバージョンに関係なくクラッシュします。現在が終了する前に解雇を呼び出すべきではないと言います。
arsenius 2013年

@arsenius使用方法のスニペットを投稿できますか?アニメーション化されていない限り、あなたが言及した問題はないはずです
Rafael Nobre 2013年

私はまた、viewDidAppearに二スニペットを入れて、それは、iOS 6の質問はここにあるの私の状況を助けるために何もしません:stackoverflow.com/questions/15654339/...
arsenius

申し訳ありませんが、最後のコメントはこちらです。iOS 5コードをviewDidAppearに移動すると、次の出力である種の無限ループが作成されます。-[UIApplicationbeginIgnoringInteractionEvents]オーバーフロー。無視します。
arsenius 2013年

3

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;
}

1

UISplitViewControllerとUISegmentedControllerを使用する比較的複雑なユニバーサルアプリがあり、Landscapeで表示する必要のあるビューがいくつかあります。 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

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

編集:まあ、私はついにそれをしました、サブクラスはとても簡単にできました。私は宣言していたnavigationControllerにしAppDelegateUINavigationControllerSubclassデフォルトの代わりにUINavigationController、その後であなたのサブクラスを変更:

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

を呼び出すことで、回転するかどうかを設定できます。 viewDidLoad

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

この調整が他の人にも役立つことを願っています、あなたのヒントに感謝します!

ヒント:を活用する

- (NSUInteger)supportedInterfaceOrientations

ビューコントローラにあるので、横向きに縦向きの目的のビューを表示したり、その逆を行ったりすることはありません。


0

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

あなたはおそらくあなたが望むものを達成することができますyそれらの方法であなたが望む方向だけを設定します。


0

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

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


0

Monotouchの場合、次のように行うことができます。

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

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


-1

project.plistに移動し、サポートされているインターフェイスの向きを追加してから、Portrait(下部のホームボタン)とPortrait(上部のホームボタン)のみを追加します。

プロジェクトの要件に応じて、方向を追加または削除できます。

ありがとう


1
アプリケーション全体ではなく、特定のビューコントローラについてです。
ムハンマドリズワン

-2

1)プロジェクト設定とinfo.plistをチェックし、必要な方向のみが選択されていることを確認します。

2)最上位のビューコントローラー(ナビゲーションコントローラー/タブバーコントローラー)に次のメソッドを追加します

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

3)アプリデリゲートに次のメソッドを追加します

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

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

}

-3

これを、ViewController回転させたくないそれぞれの.mファイルに入れます。

- (NSUInteger)supportedInterfaceOrientations
{
    //return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
    return UIInterfaceOrientationMaskPortrait;
}

詳細については、こちらをご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.