web-dev-qa-db-ja.com

shouldAutorotateToInterfaceOrientationがiOS 6で呼び出されない

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

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

これは、iOS 6の最終リリースで修正される予定のバグなのか、それとも気付いていないものが変更されたのか?

61

これを注意深く読んでください。そうしないと、ナッツを食べたり、戦ったり、揺れたり、動物のチンパンジーのように試験装置を回したりして、訪問者の携帯電話をつかんで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;
}

注意してください

UIInterfaceOrientationUIApplicationのプロパティであり、ステータスバーの方向に対応する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];を使用することもできます。これはUIDeviceOrientationを返します-デバイスの実際の向き-ただし、UIDeviceOrientationは常に等しいUIInterfaceOrientation!!!たとえば、デバイスがプレーンテーブルにある場合、予期しない値を受け取る可能性があります。

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

以前のiOS6(iOS3/4/5)とiOS6デバイスの両方をサポートしたい場合-明らかかもしれませんが、コードでshouldAutorotateToInterfaceOrientation:shouldAutorotateの両方を使用してください。

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

1. Info.plist - Supported Interface Orientations

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

plist setting in XCode (Info)

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

2. AppDelegate - application:supportedInterfaceOrientationsForWindow

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

3. Top-level view controller or RootViewController - supportedInterfaceOrientations

これは、アプリとアプリデリゲートのセットとの交差点を提供します。クラッシュを回避するには、結果がゼロ以外である必要があります。これは、コントローラーに別のメソッドがインストールされている場合を除き、デバイスが回転するたびに少なくとも1回呼び出されます。

shouldAutorotate

アプリの許可された向きに干渉し、デフォルトのBOOLYESを提供します。

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のメソッドのいずれかを使用して、「最上位」のdetailViewController(私の例ではViewControllers)で優先方向を設定できます。

1. (BOOL)shouldAutorotate

2. (NSUInteger)supportedInterfaceOrientations

3. (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
128
BootMaker

OK、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で次のいずれかを指定できます。 Supported Orientation pic

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

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

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

55
GeneCode

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

//    [self.window addSubview:self.topLevelNavigationController.view];
self.window.rootViewController = self.topLevelNavigationController;
20

ロジックの複製を必要としないiOS 5以前のコードのソリューションを次に示します。このコードをView Controllerに追加するだけで、既存の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;
}
18
user441669

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

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

このように、iOS 6より前のバージョンで使用されているのと同じロジックを使用します。もちろん、Windowsサブビューに追加するだけでなく、アプリデリゲートdidFinishLaunchingWithOptionsにrootViewControllerを適切に設定していました。

15
g1de0n_ph

また、iOS 6ビルドのshouldAutorotateおよびsupportedInterfaceOrientationsを実装するという回答が多くの回答に示されていますが、View ControllerがNavigation Controllerでホストされている場合は、ランタイムはUINavigationControllerインスタンスでこれらを呼び出し、それ以外の場合はコードを無視します。

どうやら「解決策」はUINavigationControllerをサブクラス化し、ここで説明するようにこのサブクラスにこれらの新しいメソッドを実装することです: iOS 6 UITabBarControllerは現在のUINavigationコントローラーで方向をサポート

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

これは、私が今まで見たiOSリリースで最も無意味で面倒な変更の1つでなければなりません。

11

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

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

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

またiOS6では、shouldAutorotateToInterfaceOrientation: UIViewControllerクラスのメソッドはすでに非推奨です。

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

- (BOOL)shouldAutorotate {
  return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
  return UIInterfaceOrientationMaskPortrait;
}

ところで、「ルートビューコントローラ」は、appDelegateのwindowオブジェクトの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の答え

3
MkVal

@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;
}
3
oddmeter

これは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
    }
}
3
Carlos Moura

はい、問題は、方向マスクを返すために呼び出されるwindow.rootViewControllerメソッドのみです。 supportedInterfaceOrientationsメソッドは、window.rootViewControllerとして設定されているviewControllerに実装する必要があります。しかし、ほとんどの場合、このオブジェクトはカスタムクラスではありません。 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;
}
2
Vladimir

ルートビューのみがこれらの呼び出しを処理することがわかります。私の場合、これは通常の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];
        }
}
2
ejazz
-(BOOL)shouldAutorotate
{
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;

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

    return [self shouldAutorotateToInterfaceOrientation:self.interfaceOrientation];
}
1
Kumaresan P

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);
1
Saad

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

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

これにより、最上位のView Controllerが方向を決定します。

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

- (NSUInteger)supportedInterfaceOrientations{
   if(UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]))       
      return UIInterfaceOrientationMaskPortrait;
   else
      return UIInterfaceOrientationMaskLandscape;
}
1
Daz Eddy

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

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

その働き:

- (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;
0
Nazir