65

私は MGSplitViewController を使用shouldAutorotateToInterfaceOrientationしており、回転時にマスター ビュー コントローラーのサイズを制御するために使用しています。

iOS 5 ではすべて正常に動作しますが、iOS 6 (シミュレーターと iPad の両方) ではshouldAutorotateToInterfaceOrientation呼び出されません。

これは、iOS 6 の最終リリースで修正されるはずのバグですか、それとも私が気付いていない何かが変更されたのでしょうか?

4

17 に答える 17

132

これを注意深く読んでください。そうしないと、訪問者の携帯電話をつかんだ動物園のチンパンジーのように、テスト デバイスを回転させたり、戦ったり、戦ったりして、人生の 1 ~ 2 日を失う可能性があります。遅かれ早かれ...約束:)

iOS 6 で

shouldAutorotateToInterfaceOrientation:

廃止され、置き換えられました

shouldAutorotate

これは、iOS 6 が決して呼び出さないことを意味しますshouldAutorotateToInterfaceOrientation

したがって、アプリケーションで次を使用した場合

iOS6以前(iOS5、iOS4など)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
// your code for portrait mode

}

return YES;
}

あなたが使用する必要があります

iOS 6以降以降

- (BOOL)shouldAutorotate {

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];

if (orientation == UIInterfaceOrientationPortrait) {
// your code for portrait mode

}

return YES;
}

注意してください

UIInterfaceOrientationのプロパティでUIApplicationあり、ステータス バーの向きに対応する 4 つの可能性のみが含まれます。

UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,

UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,

UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,

UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft

混同しないでください

UIDeviceOrientationこれはUIDeviceクラスのプロパティであり、7 つの可能な値が含まれています。

UIDeviceOrientationUnknown - Can not be determined

UIDeviceOrientationPortrait - Home button facing down

UIDeviceOrientationPortraitUpsideDown - Home button facing up

UIDeviceOrientationLandscapeLeft - Home button facing right

UIDeviceOrientationLandscapeRight - Home button facing left

UIDeviceOrientationFaceUp - Device is flat, with screen facing up

UIDeviceOrientationFaceDown - Device is flat, with screen facing down

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];理論的にはwhich を使用することもできます-デバイスの実際の向き-ただし、常に等しいとは限らないUIDeviceOrientationことを知っておく必要があります!!! たとえば、デバイスが無地のテーブルにある場合、予期しない値を受け取る可能性があります。UIDeviceOrientationUIInterfaceOrientation

インターフェイスの現在の向きUIInterfaceOrientation orientation = self.interfaceOrientation;を返すも使用できますが、これは のプロパティであるため、クラスでのみアクセスできます。UIInterfaceOrientationUIViewControllerUIViewController

以前の iOS6 (iOS3/4/5) と iOS6 の両方のデバイスをサポートしたい場合 (明らかな可能性があります)、コードで と の両方shouldAutorotateToInterfaceOrientation:を使用shouldAutorotateしてください。

iOS 6 からは、アプリの起動時にデバイスがチェックする 3 つのレベルと 3 つのステップがあり、必要に応じて制御する必要があります。

1. Info.plist - Supported Interface Orientations

[概要] タブでグラフィカルに設定できます。許可された方向の順序は重要です。これは、 を編集して手動で変更できinfo.plistます。デバイスは、アプリの起動時に最初の方向を選択します。[UIDevice currentDevice].orientation特に平らな面でアプリをテストする場合、不明な可能性がある場合は常にアプリの起動に問題があるため、これは重要です。

XCodeのplist設定(情報)

注意してください ( iPad ) または (iPhone) 拡張機能には他に 2 つの設定の可能性があります。それらのいずれかを使用すると、現在のデバイスまたはシミュレーターのその設定が使用され、拡張機能なしの一般的な設定は無視されます。そのため、iPhone のみのアプリを実行していて、誤ってデータがなくても plist のどこかに「Supported Interface Orientations (iPad)」行を残してしまった場合、一般設定で以前に確立したルールが無視されます (私の iPhone の例では)。 )、「アプリが iPad で実行するための要件を満たしていないことがわかりました...」というテキストでアプリが拒否される可能性があります。予期しないエラーを引き起こす可能性のあるそれを使用します。

2. AppDelegate - application:supportedInterfaceOrientationsForWindow

許可するすべての方向のビット マスク リストを返します。これは、info.plist 設定をオーバーライドします。これは、デバイスが回転するたびに少なくとも 1 回呼び出されます。

3. Top-level view controller or RootViewController - supportedInterfaceOrientations

これは、クラッシュを回避するためにゼロ以外の結果を持たなければならないアプリとアプリデリゲートのセットとの共通部分を提供します。これは、コントローラーに別のメソッドがインストールされている場合を除いて、デバイスが回転するたびに少なくとも 1 回呼び出されます。

shouldAutorotate

これは、アプリの許可された向きに干渉し、BOOLwith defaultを提供しますYES

BE CAREFUL when you use `NavigationController`

次のように、 の最上位のコントローラーとしてAppDelegate:

DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
UINavigationController *navigationController=[[UINavigationController alloc] initWithRootViewController:detailViewController];
self.window.rootViewController =nil;
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;

この場合、次のコードAppDelegateをクラスへのカテゴリ アタッチメントとして配置する必要があります。NavigationControllerこれは最上位のコントローラであり、そのサブカテゴリを作成していない場合は、方向を設定できる場所/コードがありません。設定なのでrootViewController、この場合detailViewControllerは向きを実際に確認するように強制する必要があります。

@implementation UINavigationController (OrientationSettings_IOS6)

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

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

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

@end

この後、以下のように、iOS 6 で利用可能な方法のいずれかを使用して、「最上位」ViewController(私の例ではこれは) で優先方向を設定できます。detailViewControllerViewControllers

1. (BOOL)shouldAutorotate

2. (NSUInteger)supportedInterfaceOrientations

3. (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
于 2013-02-18T14:20:04.193 に答える
55

わかりました、iOS6 iPad Simulator で動作するようになりました。わーい。これが私がしたことです:

前と後をお見せするだけです。自明のはずです。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

if (interfaceOrientation==UIInterfaceOrientationPortrait) {
 // do some sh!t

}

return YES;
}

- (BOOL)shouldAutorotate {

UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];

if (orientation==UIInterfaceOrientationPortrait) {
 // do some sh!t

}

return YES;
}

サポートされている向きについては、次のように info.plist で指定できます。 サポートされている方向 pic

またはコードを使用します:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait; // etc
}

編集: 考え直して、下位バージョン (iOS4.3/5/5.1) と 6.0 をサポートする予定がある場合は、同じコード コンテンツの両方のメソッドを含めるだけです。私のために動作します(とにかくsimで)

于 2012-09-17T08:20:15.663 に答える
20

サブビューとしてビューを追加するだけでなく、アプリウィンドウのルートコントローラーを設定するだけでうまくいきました(Rocotilosが行ったように)

//    [self.window addSubview:self.topLevelNavigationController.view];
self.window.rootViewController = self.topLevelNavigationController;
于 2012-09-21T09:35:14.950 に答える
18

ロジックを複製する必要のない、iOS 5 以前のコードのソリューションを次に示します。このコードをビュー コントローラーに追加するだけで、既存の shouldAutorotateToInterfaceOrientation メソッドから supportedInterfaceOrientations が生成されます。

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{
NSInteger mask = 0;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationLandscapeRight])
    mask |= UIInterfaceOrientationMaskLandscapeRight;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationLandscapeLeft])
    mask |= UIInterfaceOrientationMaskLandscapeLeft;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationPortrait])
    mask |= UIInterfaceOrientationMaskPortrait;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationPortraitUpsideDown])
    mask |= UIInterfaceOrientationMaskPortraitUpsideDown;
return mask;
}
于 2012-10-16T20:05:00.790 に答える
16

私にとっての簡単な修正は、このコードをルートビューコントローラーに追加することでした

- (BOOL)shouldAutorotate {
    return [self shouldAutorotateToInterfaceOrientation:self.interfaceOrientation];
}

このようにして、iOS 6 より前のバージョンで使用されていたのと同じロジックを引き続き使用します。

于 2012-09-25T09:39:00.030 に答える
11

また、多くの応答には解決策が示されていますが (iOS 6 ビルドに shouldAutorotate と supportedInterfaceOrientations を実装すること)、View Controller が Navigation Controller でホストされている場合は、いずれも問題にならないことにも注意してください。ランタイムは UINavigationController インスタンスでこれらを呼び出し、それ以外の場合はコードを無視します。

どうやら「解決策」は、UINavigationController をサブクラス化し、このサブクラスにこれらの新しいメソッドを実装することです

そして、UINavigationController を使用するすべてのコードを変更して、代わりにこの新しいサブクラスを使用する喜びがあります。

これは、私が今まで見た iOS リリースで最も無意味で厄介な破壊的変更の 1 つに違いありません。

于 2012-10-11T02:04:02.153 に答える
10

IOS 5

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

IOS 6

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations:(UIWindow *)window{

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


    //    return UIInterfaceOrientationMaskLandscape;
    return 24;
}
于 2012-10-10T06:55:21.007 に答える
3

以下は、Apple の iOS SDK、XCode4.5+ からの引用です (UIViewController クラス リファレンス、ビューの回転の処理を参照)。

iOS 6 では、アプリは、アプリの Info.plist ファイルで定義されたインターフェイスの向きをサポートします。View Controller はsupportedInterfaceOrientationsメソッドをオーバーライドして、サポートされている向きのリストを制限できます。通常、システムはこのメソッドを、ウィンドウのルート ビュー コントローラー、または画面全体に表示されるビューコントローラーでのみ呼び出します。子View Controllerは、親View Controllerによって提供されたウィンドウの一部を使用し、どの回転がサポートされているかについての決定に直接参加しなくなりました。

また、iOS6ではUIViewControllerクラスのshouldAutorotateToInterfaceOrientation:メソッドが廃止されています。

したがって、ルート ビュー コントローラーで、ff を実行します。

- (BOOL)shouldAutorotate {
  return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
  return UIInterfaceOrientationMaskPortrait;
}

ところで、「ルート ビュー コントローラー」は、appDelegate のウィンドウオブジェクトのrootViewControllerとして設定した任意の UIViewController サブクラスです。通常、これは appDelegate のapplication:didFinishLaunchingWithOptions:メソッドで行います。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  // Override point for customization after application launch.
  self.window.rootViewController = [FFDashboardController create];
  [self.window makeKeyAndVisible];
  return YES;
}

UINavigationController をルート VC として使用する方法については、Vladimir's answerを参照してください。

于 2012-11-15T14:04:08.507 に答える
3

これは、iOS6 と Xcode 4.5 GM でうまくいきました。

AppDelegate.m について

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    .....

    //   self.window.rootViewController = self.navigationController;

    [window setRootViewController:navigationController];

    .....

    return YES;
}

ViewControllerで:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration

{
    if (UIInterfaceOrientationIsLandscape(interfaceOrientation))

    {
      // landscape
    }
    else
    {
      //portrait
    }
}
于 2012-09-14T03:33:26.927 に答える
3

@Rocotilos への返信として、フォーラムの他の場所では見たことのない、自分のコードで発生した補遺を入手しました。アプリのライフ サイクルの最初の段階で、shouldAutorotate メソッドで方向が不明な状況に遭遇しました。これにより、アプリが横向きでビューを正しく表示できませんでした。シミュレーターで数回回転させた後、正常に機能していました。

私のシナリオは、横向きのレイアウトが必要な場所にポップされる特定のビューがあるということです。そのため、shouldAutorotate が YES を返すことは望ましくありません。一部の人にとってはまれなケースかもしれませんが、これを診断するのに十分な時間を費やしたので、伝えたいと思いました. これが役に立てば幸いです。

- (BOOL) shouldAutorotate {

    BOOL shouldRotate = NO;
    UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];

    if ([self IsCaseWhereWeDontWantLandscapeAutorotation]) {
        shouldRotate = NO;
    } else if (orientation == UIDeviceOrientationUnknown) {
        //Handle the case where the device's orientation is not yet known
        shouldRotate = YES;
    } else {
        //Handle the normal case
        shouldRotate = (orientation == UIInterfaceOrientationMaskLandscape);
    }

    return shouldRotate;
}
于 2012-11-26T02:00:38.627 に答える
2

はい、問題は、方向マスクを返すために呼び出される window.rootViewController メソッドのみです。したがって、window.rootViewController として設定されている viewController にsupportedInterfaceOrientationsメソッドを実装する必要があります。しかし、ほとんどの場合、このオブジェクトは UINavigationController などのカスタム クラスではありません。考えられる解決策の 1 つは、UINavigationController をサブクラス化することです。しかし、Apple は、「このクラスはサブクラス化を意図していません」と言っているので、別の UIViewController を使用して向きを処理し、UINavigationController を子として追加したいと考えています。

MyRootViewController * myRoot = [MyRootViewController new];
self.window.rootViewController = myRoot;
[myRoot addChildViewController:navigationController];
[myRoot.view addSubview:navigationController.view];

および MyRootViewController でメソッドを実装します。

- (BOOL)shouldAutorotate {
 return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    // return your mask here e.g.:
    return UIInterfaceOrientationMaskPortrait;
}
于 2012-10-30T11:25:55.443 に答える
2

これらの呼び出しを処理するのはルート ビューだけであることがわかります。私の場合、これは通常の UINavigationController でした。これを、メソッドを追加したサブクラス化されたファイルに変更する必要がありました。

私の場合、ルート ビューのポートレートのみが必要で、残りのポートレートとランドスケープが必要でした。

Appdelegate.h

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    S2MBookAppRootViewController *masterViewController = [[[S2MBookAppRootViewController alloc] initWithNibName:pref.rootNibName bundle:nil] autorelease];
    self.navigationController = [[[S2MBookAppNavController alloc] initWithRootViewController:masterViewController] autorelease];

    self.window.rootViewController = self.navigationController;


    [self.window makeKeyAndVisible];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:YES];

    return YES;
}

S2MBookAppNavController (UINavigationController のサブクラス)

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if([self.viewControllers count] == 1) return UIInterfaceOrientationMaskPortrait;
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape;
}

更新: 方向を強制する場合 (ナビゲーション コントローラーで新しいビューをプッシュする場合)、これを試してください。

UINavigationController も独自のデリゲートにします。

@interface S2MBookAppNavController : UINavigationController <UINavigationControllerDelegate>

@end

そして.mファイルで

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.delegate = self;
    // Do any additional setup after loading the view.
}

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        if ([UIViewController respondsToSelector:@selector(attemptRotationToDeviceOrientation)]) {
            //present/dismiss viewcontroller in order to activate rotating.
            UIViewController *mVC = [[[UIViewController alloc] init] autorelease];
            [self presentModalViewController:mVC animated:NO];
            [self dismissModalViewControllerAnimated:NO];
        }
}
于 2012-10-23T15:01:56.297 に答える
1

UINavigationController に一連のビュー コントローラーがあり、そのうちの 1 つはランドスケープのみである必要がありました。UINavigationController をサブクラス化し、次のコードを追加して修正しました。

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

これにより、最上位のビュー コントローラーが向きを指示するようになります。

ただし、落とし穴があります。横向きに制限されている VC から任意の向きをサポートする VC に移行する場合、新しいビューは電話の向きに関係なく横向きに表示されます。これに対抗するために、無制限のviewControllerに次のコードを追加しました。

- (NSUInteger)supportedInterfaceOrientations{
   if(UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]))       
      return UIInterfaceOrientationMaskPortrait;
   else
      return UIInterfaceOrientationMaskLandscape;
}
于 2013-01-23T12:45:44.867 に答える
1

Apple は ios6 からの shouldautorate メソッドを廃止し、代わりにこれらのメソッドを使用します。xcode ドキュメントを参照してください

- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0);
- (NSUInteger)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0);
// Returns interface orientation masks.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0);
于 2012-11-13T13:30:15.540 に答える
1

UIKit という見出しの下のメモ: http://developer.apple.com/library/ios/#releasenotes/General/RN-iOSSDK-6_0/_index.html%23//apple_ref/doc/uid/TP40012166-CH1- SW19は答えの手がかりをいくつか与えてくれますが、それが全体像ではありません。まだ全体像は把握できていませんが、iOS 6.0 RTM についてこれまでにわかったことは次のとおりです。

サポートされている向きを実際に制限するのではなく、代わりに、ユーザーがデバイスを回転させたために何かをしたい場合は、ロジックを移動できます

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

- (void)viewWillLayoutSubviews

代わりは。

これはおそらく直接の代替品になる可能性がありますが、下位レベルの iOS バージョンではまだテストしていません。

サポートされている向きを制限したい場合は、次のUIApplicationDelegateレベルでそれを行う必要があります

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window

supportedInterfaceOrientationsForWindow:ドキュメントには、「システムは、アプリのメソッドによって返された値と、最上位のフルスクリーン コントローラーの supportedInterfaceOrientations メソッドによって返された値を交差させることによって、向きがサポートされているかどうかを判断する」と記載されています。しかし、実験では、システムがサポートされているView Controllerを無視することがわかりました

-(NSUInteger)supportedInterfaceOrientations

メソッドが呼び出されても戻り値。

于 2012-10-03T05:37:09.287 に答える
1
-(BOOL)shouldAutorotate
{
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;

    if (orientation == UIDeviceOrientationUnknown) {
        return YES;
    }

    return [self shouldAutorotateToInterfaceOrientation:self.interfaceOrientation];
}
于 2013-05-10T05:49:59.587 に答える
0

私のために働く:

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
    if ([self isKindOfClass:[YourViewController class]]) { // Your view class
        orientations |= UIInterfaceOrientationMaskPortraitUpsideDown;
    }
    return orientations;
}

オリエンテーション:

orientations |= UIInterfaceOrientationMaskLandscapeLeft;
orientations |= UIInterfaceOrientationMaskLandscapeRight;
于 2013-03-08T10:35:01.677 に答える