MGSplitViewControllerを使用しており、usingshouldAutorotateToInterfaceOrientation
を使用して、回転時のマスタービューコントローラーのサイズを制御しています。
IOS 5ではすべて正常に動作しますが、iOS 6(シミュレーターとiPadの両方)shouldAutorotateToInterfaceOrientation
は呼び出されません。
これは、iOS 6の最終リリースで修正される予定のバグなのか、それとも気付いていないものが変更されたのか?
これを注意深く読んでください。そうしないと、ナッツを食べたり、戦ったり、揺れたり、動物のチンパンジーのように試験装置を回したりして、訪問者の携帯電話をつかんで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];
を使用することもできます。これは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
が不明である可能性がある場合、特にアプリを平らな面でテストする場合は常にアプリの起動に問題があるため、重要です。
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
アプリの許可された向きに干渉し、デフォルトのBOOL
で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
のメソッドのいずれかを使用して、「最上位」のdetailViewController
(私の例ではViewControllers
)で優先方向を設定できます。
1. (BOOL)shouldAutorotate
2. (NSUInteger)supportedInterfaceOrientations
3. (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
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で次のいずれかを指定できます。
または、コードを使用します:
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait; // etc
}
編集:考え直して、下位バージョン(iOS4.3/5/5.1)および6.0をサポートする予定の場合は、同じコードコンテンツの両方のメソッドを含めるだけです。私のために働く(とにかくシムで)
サブウィンドウとしてビューを追加するだけでなく、アプリウィンドウのルートコントローラーを設定する(ロコティロスが行ったように)
// [self.window addSubview:self.topLevelNavigationController.view];
self.window.rootViewController = self.topLevelNavigationController;
ロジックの複製を必要としない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;
}
私のための簡単な修正は、ルートビューコントローラーにこのコードを追加することでした
- (BOOL)shouldAutorotate {
return [self shouldAutorotateToInterfaceOrientation:self.interfaceOrientation];
}
このように、iOS 6より前のバージョンで使用されているのと同じロジックを使用します。もちろん、Windowsサブビューに追加するだけでなく、アプリデリゲートdidFinishLaunchingWithOptionsにrootViewControllerを適切に設定していました。
また、iOS 6ビルドのshouldAutorotateおよびsupportedInterfaceOrientationsを実装するという回答が多くの回答に示されていますが、View ControllerがNavigation Controllerでホストされている場合は、ランタイムはUINavigationControllerインスタンスでこれらを呼び出し、それ以外の場合はコードを無視します。
どうやら「解決策」はUINavigationControllerをサブクラス化し、ここで説明するようにこのサブクラスにこれらの新しいメソッドを実装することです: iOS 6 UITabBarControllerは現在のUINavigationコントローラーで方向をサポート
そして、UINavigationControllerを使用して、代わりにこの新しいサブクラスを使用するすべてのコードを変更することができます。
これは、私が今まで見たiOSリリースで最も無意味で面倒な変更の1つでなければなりません。
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;
}
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の答え 。
@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;
}
これは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
}
}
はい、問題は、方向マスクを返すために呼び出される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;
}
ルートビューのみがこれらの呼び出しを処理することがわかります。私の場合、これは通常の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];
}
}
-(BOOL)shouldAutorotate
{
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
if (orientation == UIDeviceOrientationUnknown) {
return YES;
}
return [self shouldAutorotateToInterfaceOrientation:self.interfaceOrientation];
}
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);
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;
}
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;