31

この質問は、iOSデバイスの回転とUINavigationControllerの複数の制御されたビューに関するものです。一部のビューは縦向きに制限する必要があり、一部は自由に自動回転する必要があります。3つのビューを使用して最も単純なセットアップを作成しようとすると、自動回転の動作にいくつかの非常に厄介な癖があることに気付くでしょう。ただし、シナリオは非常に単純なので、自動ローテーションの実装が正しく行われていないか、何かを忘れていると思います。

私は奇妙さを示す非常に基本的なデモアプリを持っていて、それが実際に動作していることを示すビデオを作成しました。

セットアップは非常に基本的です。3つのViewControllerは、と呼ばれ、FirstViewControllerすべてがクラス名のラベルを表示し、デバイスが縦向きの場合にYESを返すを拡張します。SecondViewControllerは、このメソッドをオーバーライドして、すべての回転を許可します。3つの具象クラスはすべて、いくつかの色付きの正方形を追加して、コントローラーをオン/オフすることでビュー間を移動できるようにします。これまでのところ、非常に単純なシナリオだと思います。SecondViewControllerThirdViewControllerAbstractViewControllershouldAutorotateToInterfaceOrientation:UINavigationController

デバイスを縦向きまたは横向きに持っている場合、これは私が達成したいだけでなく、期待する結果です。最初の画像では、すべてのビューが「直立」していることがわかります。2番目の画像では、2番目のビューコントローラーのみがデバイスの向きを逆回転させていることがわかります。明確にするために、横向きモードの2番目のビューから3番目のビューに移動できるはずですが、その3番目は縦向きのみをサポートしているため、縦向きでのみ表示する必要があります。結果に問題がないかどうかを確認する最も簡単な方法は、キャリアバーの位置を確認することです。

ポートレートモードでのデバイスの予想されるビューの向き 横向きモードでのデバイスの予想されるビューの向き

しかし、実際の結果は完全に異なるため、この質問はここにあります。デバイスを回転させたときに表示されているビューに応じて、また次に移動するビューに応じて、ビューは回転しません(具体的には、didOrientFromInterfaceOrientation:メソッドが呼び出されることはありません)。2番目の風景にいて、3番目に移動すると、2番目と同じ向きになります(=悪い)。ただし、2番目から最初に戻ると、画面が「強制」ポートレートモードに回転し、持ち方に関係なく、キャリアバーがデバイスの物理的な上部に表示されます。ビデオはこれをより詳細に示しています。

横向きモードでのデバイスの実際のビューの向き

私の質問は2つあります:

  1. 最初のViewControllerが回転して戻るのに、3番目は回転しないのはなぜですか?
  2. 一部のビューのみを自動回転させ、他のビューは自動回転させたくない場合に、ビューから正しい動作を取得するには、何をする必要がありますか?

乾杯、EP。

編集:賞金をかける前の最後の手段として、私はこの質問を完全に書き直して、より短く、より明確に、そしてうまくいけば、答えを与えるためにより魅力的にしました。

4

5 に答える 5

8

簡単に言うと、UINavigationControllerを使用しているため、希望どおりに機能しません。Appleのドキュメントから:

UIViewControllerがデバイスと一緒に回転しないのはなぜですか?

UITabBarControllerまたはUINavigationControllerのすべての子ViewControllerは、共通の方向セットに同意しません。

すべての子ViewControllerが正しく回転することを確認するには、各タブまたはナビゲーションレベルを表す各ViewControllerにshouldAutorotateToInterfaceOrientationを実装する必要があります。その回転が発生するためには、それぞれが同じ方向に同意する必要があります。つまり、それらはすべて、同じ方向位置に対してYESを返す必要があります。

ビューの回転の問題について詳しくは、こちらをご覧ください。

やりたいことのために、独自のビュー/コントローラースタック管理をロールする必要があります。

于 2011-02-22T05:09:39.427 に答える
5

アプリデリゲートでブール値を作成して、必要な方向を制御します。たとえば、ブール値を作成してポートレートを有効にし、ビューコントローラーでポートレートを共有アプリケーションで有効にします。

ビューコントローラで、必要な向きを有効または無効にします。

((APPNAMEAppDelegate *)[[UIApplication sharedApplication] delegate]).enablePortrait= NO;

AppDelegateで。

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    NSLog(@"Interface orientations");
    if(!enablePortrait)
        return UIInterfaceOrientationMaskLandscape;
    return UIInterfaceOrientationMaskLandscape|UIInterfaceOrientationMaskPortrait;
}

これらのメソッドは、デバイスを回転させるたびに実行されます。これらのBOOLに基づいて、必要な方向を有効にします。

于 2012-12-04T09:12:11.597 に答える
4

数年前に同様の質問があり、多くの回答がありました。その質問に対する誰かからの最近の回答は次のとおり
です。iPhoneの向きを設定するための文書化された方法はありますか?

私が理解していることから、これは多くの人が抱えている問題であり、ほとんどの場合、ハックがそれを修正する唯一の方法です。まだ見たことがない場合は、そのスレッドを調べて、何かがうまくいくかどうかを確認してください。

ちなみに、shouldAutorotateで何かを呼び出していたときに同様の問題が発生し、viewWillAppearそれを修正するためのコードを追加しました。正直なところ、それが機能したかどうかは思い出せず、試してみるためのMacはもうありませんが、コードを見つけたので、インスピレーションが得られる場合に備えてここに貼り付けます。

- (void)viewWillAppear:(BOOL)animated{
  UIInterfaceOrientation o;
  switch ([UIDevice currentDevice].orientation) {
    case UIDeviceOrientationPortrait:
        o = UIInterfaceOrientationPortrait;
        break;
    case UIDeviceOrientationLandscapeLeft:
        o = UIInterfaceOrientationLandscapeLeft;
        break;
    case UIDeviceOrientationLandscapeRight:
        o = UIInterfaceOrientationLandscapeRight;
        break;
    default:
        break;
  }

  [self shouldAutorotateToInterfaceOrientation:o];
}
于 2011-02-20T07:38:29.870 に答える
2

iOS 6では、これは非常に単純な問題になっています。自動回転するビュー用の特別なクラスを作成するだけです。次に、rootVCにこれを追加します。

-(BOOL)shouldAutorotate{
       BOOL should = NO;

       NSLog(@"%@", [self.viewControllers[self.viewControllers.count-1] class]);
       if ([self.viewControllers[self.viewControllers.count-1] isKindOfClass:[YourAutorotatingClass class]]) {
             should = YES;
       }


       return should;
}

これは古い質問だと思いますが、言及する価値があると思いました。

于 2013-02-10T21:51:09.773 に答える
2

このハックは使用しないでください。APPLEは「プライベートAPI」の使用に基づいてアプリを拒否します

参考までに、ここに答えを残しておきますが、プライベートAPIの使用はレビューボードをすり抜けることはありません。私は今日何かを学びました:D @younceがAppleのドキュメントを正しく引用しているので、私が望むことはUINavigationControllerでは達成できません。

私には2つの選択肢がありました。最初に、私はそれをしている間に遭遇したであろうすべての恐怖で、私自身のナビゲーションコントローラーの代用品を書くことができたでしょう。次に、UIDeviceの文書化されていない機能を使用して、回転をViewControllerにハッキングすることができました。setOrientation:animated:

2つ目は魅力的に簡単だったので、私はそれを選びました。これが私がしたことです。セッターが存在しないことに関するコンパイラーの警告を抑制するためのカテゴリーが必要です。

@interface UIDevice (UndocumentedFeatures) 
-(void)setOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated;
-(void)setOrientation:(UIInterfaceOrientation)orientation;
@end

次に、でサポートされている向きを確認する必要がありますviewWillAppear:。ここで使用されているUIDeviceメソッドの横に、モーダルビューコントローラーを表示して縦向きを強制することもできますが、これはアニメーション化されずに即座に行われるため、これが私の推奨される方法です。

-(void)viewWillAppear:(BOOL)animated {
    UIDevice *device = [UIDevice currentDevice];
    UIDeviceOrientation realOrientation = device.orientation;

    if ([self shouldAutorotateToInterfaceOrientation:realOrientation]) {
        if (realOrientation != [UIApplication sharedApplication].statusBarOrientation) {

            // Resetting the orientation will trigger the application to rotate
            if ([device respondsToSelector:@selector(setOrientation:animated:)]) {
                [device setOrientation:realOrientation animated:animated];
            } else {
                // Yes if Apple changes the implementation of this undocumented setter,
                // we're back to square one.
            }
        }
    } else if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait]) {
        if ([device respondsToSelector:@selector(setOrientation:animated:)]) {

            // Then set the desired orientation
            [device setOrientation:UIDeviceOrientationPortrait animated:animated];

            // And set the real orientation back, we don't want to truly mess with the iPhone's balance system.
            // Because the view does not rotate on this orientation, it won't influence the app visually.
            [device setOrientation:realOrientation animated:animated];
        }
    }
}

秘訣は、内部デバイスの向きを常にデバイスの「実際の」向きに保つことです。これを変更し始めると、アプリの回転のバランスが崩れます。

しかし、私が今知っているように、これはあなたのアプリを拒否させる確実な方法です。したがって、オプション2は悪いオプションです。そのNavigationControllerを書き直すか、すべてのビューで同じ方向セットをサポートするようにします。

乾杯、EP。

于 2011-02-20T12:15:05.037 に答える