57

たとえば10個のビューコントローラーを備えたアプリを提供しました。ナビゲーションコントローラーを使用してロード/アンロードします。

1つを除くすべてがポートレートモードです。7番目のVCが横向きであるとします。ロードされたときに横向きで表示する必要があります。

IOS 6で向きを縦向きから横向きに強制する方法を提案してください(IOS 5でも機能するのが良いでしょう)。

これが私がIOS6の前にそれをやっていた方法です:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    UIViewController *c = [[[UIViewController alloc]init] autorelease];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

モーダルVCを提示および却下すると、アプリはその方向を確認する必要があったためshouldAutorotateToInterfaceOrientation、呼び出されていました。

私がIOS6で試したこと:

- (BOOL)shouldAutorotate{
    return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationLandscapeLeft;
}

ロード時に、コントローラーは縦向きのままになります。デバイスを回転させた後、向きは問題なく変化します。ただし、負荷時にコントローラーを自動的に回転させて横向きにする必要があるため、ユーザーはデータを正しく表示するためにデバイスを回転させる必要があります。

別の問題:デバイスを縦向きに回転させた後、向きは縦向きになりますが、で指定したsupportedInterfaceOrientationsだけUIInterfaceOrientationMaskLandscapeです。なぜそれが起こるのですか?

また、上記の3つのメソッドのどれも呼び出されていません。

いくつかの(有用な)データ:

  1. 私のplistファイルでは、3つの方向を指定しました-逆さまを除いてすべて。
  2. プロジェクトはXcode4.3IOS5で開始されました。xibsを含むすべてのクラスはXcode4.5IOS 6より前に作成され、現在は最後のバージョンを使用しています。
  3. plistファイルでは、ステータスバーが表示に設定されています。
  4. xibファイル(横向きにしたいファイル)では、ステータスバーは「なし」で、向きは横向きに設定されています。

どんな助けでも大歓迎です。ありがとう。

4

13 に答える 13

43

わかりました、皆さん、私は私の解決策を投稿します。

私が持っているもの:

  1. いくつかのビュー コントローラーを備えたビュー ベースのアプリケーション。(これはナビゲーション ベースでしたが、向きの問題により、ビュー ベースにする必要がありました)。
  2. すべてのビュー コントローラは、1 つを除いて縦向きです - 横向きの左。

タスク:

  1. ユーザーがデバイスをどのように保持していても、View Controller の 1 つは自動的に横向きに回転する必要があります。他のすべてのコントローラーは縦向きである必要があり、横向きのコントローラーを離れた後、ユーザーがデバイスをどのように持っているかに関係なく、アプリは強制的に縦向きに回転する必要があります。
  2. これは、IOS 5.x と同様に IOS 6.x でも機能する必要があります。

行け!

更新は@Ivan Vučicaによって提案されたマクロを削除しました)

すべての PORTRAIT ビュー コントローラーで、次のように自動回転メソッドをオーバーライドします。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

2 つのアプローチを確認できます。1 つは IOS 5 用で、もう 1 つは IOS 6 用です。

LANDSCAPE ビュー コントローラについても同じですが、いくつかの追加と変更があります。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    [image_signature setImage:[self resizeImage:image_signature.image]];
    return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    [image_signature setImage:[self resizeImage:image_signature.image]];
    return UIInterfaceOrientationMaskLandscapeLeft;
}

注意: IOS 5で自動回転を強制するには、次を追加する必要があります。

- (void)viewDidLoad{
    [super viewDidLoad];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
        [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];    
}

同様に、LANDSCAPE コントローラーを離れた後、ロードするコントローラーが何であれ、IOS 5 の自動回転を再度強制する必要がありますがUIDeviceOrientationPortrait、PORTRAIT コントローラーに移動するときに を使用します。

- (void)viewDidLoad{
        [super viewDidLoad];
        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
            [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];    
    }

最後に (少し奇妙ですが)、IOS に応じて、コントローラーから別のコントローラーに切り替える方法を変更する必要があります。

NSObject クラス "Schalter" (ドイツ語の "Switch") を作成します。

Schalter.h で次のように言います。

#import <Foundation/Foundation.h>

@interface Schalter : NSObject
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease;
@end

Schalter.m で次のように言います。

#import "Schalter.h"
#import "AppDelegate.h"

@implementation Schalter
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease{

    //adjust the frame of the new controller
    CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
    CGRect windowFrame = [[UIScreen mainScreen] bounds];
    CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height);
    VControllerToLoad.view.frame = firstViewFrame;

    //check version and go
    if (IOS_OLDER_THAN_6)
        [((AppDelegate*)[UIApplication sharedApplication].delegate).window addSubview:VControllerToLoad.view];
    else
        [((AppDelegate*)[UIApplication sharedApplication].delegate).window setRootViewController:VControllerToLoad];

    //kill the previous view controller
    [VControllerToRelease.view removeFromSuperview];
}
@end

今、これは Schalter を使用する方法です (倉庫コントローラーから製品コントローラーに移動するとします):

#import "Warehouse.h"
#import "Products.h"

@implementation Warehouse
Products *instance_to_products;

- (void)goToProducts{
    instance_to_products = [[Products alloc] init];
    [Schalter loadController:instance_to_products andRelease:self];
}

bla-bla-bla your methods

@end

もちろん、instance_to_productsオブジェクトを解放する必要があります:

- (void)dealloc{
     [instance_to_products release];
     [super dealloc];
}

さて、これです。反対票を投じることをためらわないでください、私は気にしません。これは、評判ではなく、解決策を探している人向けです。乾杯!サヴァ・マザレ。

于 2012-10-04T11:00:30.227 に答える
34

これはうまくいくはずです.iOS 6より前のバージョンに似ていますが、UINavigationController.

UIViewController *portraitViewController = [[UIViewController alloc] init];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController];
[self.navigationController presentModalViewController:nc animated:NO];
[self.navigationController dismissModalViewControllerAnimated:NO];

次の をプッシュする前に、これを呼び出していUIViewControllerます。現在が横向きであっても、次に押さUIViewControllerれたものが縦向きモードで表示されるように強制しますUIViewController(縦向きから横向きでも機能するはずです)。私にとってはiOS 4 + 5 + 6で動作します。

于 2012-10-01T15:14:22.533 に答える
14

最善の解決策は、アップルの公式ドキュメントに固執することだと思います。それによると、私は次の方法を使用し、すべてが iOS 5 および 6 で非常にうまく機能しています。私の VC では、次の方法をオーバーライドします。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}

iOS 6 のメソッド。最初のメソッドは、サポートされている方向マスクを返します (名前が示すように)

-(NSUInteger)supportedInterfaceOrientations{

    return UIInterfaceOrientationMaskPortrait;
}

2 つ目は、VC が表示されるときにどのインターフェイスの向きが優先されるかを VC に伝えます。

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

必要な方向に縦を変更するだけです;)このソリューションはスムーズに機能します。この単純なソリューションを回避するマクロやその他のものを作成するという考えは好きではありません。この助けを願って...

于 2012-11-13T11:39:47.833 に答える
7

私は同じ問題を抱えていました.私のアプリケーションには27のビューがあり、そのうちの26は縦向きで、すべての向きは1つだけです(画像ビューア:))。すべてのクラスにマクロを追加してナビゲーションを置き換えることは、私が満足できる解決策ではありませんでした...

そのため、UINavigationController の仕組みをアプリに保持し、これを他のコードに置き換えないようにしたいと考えました。

何をすべきか:

@1 メソッド didFinishLaunchingWithOptions のアプリケーション デリゲート内

if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
    // how the view was configured before IOS6
    [self.window addSubview: navigationController.view];
    [self.window makeKeyAndVisible];
}
else
{
    // this is the code that will start the interface to rotate once again
    [self.window setRootViewController: self.navigationController];
}

@2 navigationController は autorotation に対して YES で応答するだけなので、いくつかの制限を追加する必要があります: UINavicationController -> YourNavigationController を拡張し、Interface Builder でリンクします。

@3 ナビゲーション コントローラーの「煩わしい新しいメソッド」をオーバーライドします。

このクラスはこのアプリケーション専用のカスタムであるため、そのコントローラーに対して責任を負い、代わりに応答することができます。

-(BOOL)shouldAutorotate {

    if ([self.viewControllers firstObject] == YourObject)
    {
         return YES;
    }
    return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
     if ([self.viewControllers firstObject] == YourObject)
    {
         return UIINterfaceOrientationMaskLandscape;
    }
    return UIInterfaceOrientationMaskPortrait;
}

これがお役に立てば幸いです。

于 2012-10-14T23:47:26.560 に答える
3

iOS 6 リリース ノートから:

現在、iOS コンテナー (UINavigationController など) は、自動回転する必要があるかどうかを判断するために、子に相談しません。

メッセージを階層を下って VC にrootViewController渡しますか?shouldAutoRotateViewController

于 2012-09-28T13:55:08.750 に答える
2

成功しなかった多くの異なる可能な解決策を試した後、私は次の解決策を思いつきました。

レシピを用意しました:)。

問題: iOS 6 でナビゲーション コントローラーを使用してビュー コントローラーの向きを変更する必要があります。

解決:

ナビゲーションの提案

ステップ 1.画像が示すように、モーダル セグエをランドスケープおよびポートレート UInavigationControllers にトリガーする 1 つの初期 UIviewcontroler....

より深く UIViewController1 では、Appdelegate のグローバル変数に従って 2 つのセグエ アクションが必要です。

-(void)viewDidAppear:(BOOL)animated{
    if([globalDelegate changeOrientation]==0){
        [self performSegueWithIdentifier:@"p" sender:self];
    }
    else{
        [self performSegueWithIdentifier:@"l" sender:self];
    }

}

また、ポートレートに戻る方法も必要です &| 風景....

- (IBAction)dimis:(id)sender {
    [globalDelegate setChangeOrientation:0];
    [self dismissViewControllerAnimated:NO completion:nil];
}

ステップ 2.各 NavigationController で最初にプッシュされた UiViewControllers は...

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

-(BOOL)shouldAutorotate{
    return YES;
}

ステップ 3. UInavigationController のサブクラスで supportedInterfaceOrientations メソッドを上書きします....

customNavigationController には .....

-(NSUInteger)supportedInterfaceOrientations{
    if([self.visibleViewController isKindOfClass:[ViewController2 class]]){

        return UIInterfaceOrientationMaskPortrait;
    }
    else{
        return UIInterfaceOrientationMaskLandscape;

    }

}

ステップ 4.ストーリーボードまたはコードで、ポートレートとランドスケープの両方の uinavigationcontrollers に対して、wantsFullScreenLayout フラグを yes に設定します。

于 2013-03-07T22:48:04.450 に答える
2

OP pre-ios6 (モーダル VC の提示と破棄) と同じ方法を使用して、単一のビュー コントローラーを横向きモード (その他はすべて縦向き) で表示しました。横向きのVCが縦向きに表示されているiOS6で壊れました。

これを修正するために、ランドスケープ VC に preferredInterfaceOrientationForPresentation メソッドを追加しました。現在、OS 5 および OS 6 で正常に動作しているようです。

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

- (BOOL)shouldAutorotate
{
return NO;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{    
return UIInterfaceOrientationLandscapeLeft;
}
于 2013-02-20T02:08:05.430 に答える
1

カテゴリを使用するかサブクラス化された へのセグエを試みてUINavigationController、目的の方向を指定してから、目的の VC へのセグエを試みます。詳細はこちらをご覧ください

于 2012-09-28T14:03:29.050 に答える
0

UINavigationController をサブクラス化し、次のようにナビゲーション コントローラーの supportedInterfaceOrientations をオーバーライドすることで解決しました。

- (NSUInteger)supportedInterfaceOrientations
{
     return [[self topViewController] supportedInterfaceOrientations];
}

すべてのコントローラーは、サポートされているInterfaceOrientations を目的の向きで実装しました。

于 2014-02-14T23:08:11.697 に答える
0

Info.plist ファイルに移動し、変更を加えますここに画像の説明を入力

于 2013-08-02T21:59:14.277 に答える
-1

次のソリューションを使用しました。他のビュー コントローラーとは方向が異なる 1 つのビュー コントローラーでは、prepareForSegueメソッドに方向チェックを追加しました。宛先のView Controllerが、現在表示されているものとは異なるインターフェイスの向きを必要とする場合、シーク中にインターフェイスを強制的に回転させるメッセージが送信されます。

#import <objc/message.h>

...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if(UIDeviceOrientationIsLandscape(self.interfaceOrientation))
    {
        UIInterfaceOrientation destinationOrientation;

        if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]])
        {
            UINavigationController *navController = (UINavigationController *)[segue destinationViewController];
            destinationOrientation = [navController.topViewController preferredInterfaceOrientationForPresentation];
        } else
        {
            destinationOrientation = [[segue destinationViewController] preferredInterfaceOrientationForPresentation];
        }

        if ( destinationOrientation == UIInterfaceOrientationPortrait )
        {
            if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
            {
                objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );
            }
        }
    }
}
于 2013-07-11T17:01:20.173 に答える