0

縦向きのビューと横向きのビューが含まれていることを除いて、両方とも同じ 2 つのストーリーボードを作成しました。

一部のビューのレイアウトは縦向きと横向きで完全に変わるため、自動サイズ変更マスクを使用したくありません。過去にコードでビューのコントロールを手動で移動しましたが、今回はより簡単な方法を求めていました:)

私が見つけた最も近い解決策は、「benyboariu」からのものでした - Storyboards orientation support for xCode 4.2?

これは私が使用しているコードで、iOS 5.x では正常に動作しますが、iOS 6.x では動作しません。

- (void)updateLandscapeView
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;

if (deviceOrientation == UIDeviceOrientationUnknown)
{
    if ([[UIScreen mainScreen] bounds].size.height > [[UIScreen mainScreen] bounds].size.width)
    {
        deviceOrientation = UIDeviceOrientationPortrait;
        self.appDelegate.isShowingLandscapeView = NO;
    }
    else
    {
        deviceOrientation = UIDeviceOrientationLandscapeLeft;
        self.appDelegate.isShowingLandscapeView = YES;
    }
}

if (UIDeviceOrientationIsLandscape(deviceOrientation) && !self.appDelegate.isShowingLandscapeView)
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Landscape" bundle:[NSBundle mainBundle]];
    UIViewController * landscape = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController-Landscape"];
    self.appDelegate.isShowingLandscapeView = YES;
    [UIView transitionWithView:landscape.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
        self.view = landscape.view;
    } completion:NULL];
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) && self.appDelegate.isShowingLandscapeView)
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Portrait" bundle:[NSBundle mainBundle]];
    UIViewController * portrait = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController"];
    self.appDelegate.isShowingLandscapeView = NO;
    [UIView transitionWithView:portrait.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
        self.view = portrait.view;
    } completion:NULL];
}
}

iOS 6.x でのデバッグ時に発生するエラーは次のとおりです。

キャッチされない例外 'UIViewControllerHierarchyInconsistency' が原因でアプリを終了しています。UIView を表示: 0x108276b0; フレーム = (0 0; 568 268); 自動サイズ変更 = RM+BM; アニメーション = { position=CABasicAnimation: 0x10815c60; 境界 = CABasicAnimation: 0x1082a5e0; }; layer = CALayer: 0x10827710 は RootViewController: 0x10821f10 に関連付けられています。このビューを RootViewController: 0x961a150 に関連付ける前に、この関連付けをクリアしてください。

通常、NIB からビュー コントローラーのリンクを解除してこの種のエラーを修正しますが、ストーリーボードでそれを行うことはできません。

誰でもアイデアはありますか?

4

2 に答える 2

0

さて、この問題を解決するためにあらゆる種類の方法を試した後、iOS 5.x および 6.x で動作するこのソリューションを思いつきました。

基本的に、問題はナビゲーションコントローラーが原因であるように見えるので、代わりに

self.view = landscape.view;

また

self.view = portrait.view;

ナビゲーション コントローラー スタックに含まれるすべてのビュー コントローラーを置き換える必要があります。

以下のコードで行っていることは、ナビゲーション コントローラー スタック内のすべてのビュー コントローラーの NSMutableArray を作成することです。次に、各ビュー コントローラーをループし、ビュー タグを取得して、どのビューを置き換える必要があるかを判断します。次に、View Controllerを横向きまたは縦向きのバージョンに置き換え、ナビゲーションコントローラーのView Controller配列を変更された配列に設定して、すべてのView Controllerを置き換えます。

if (UIDeviceOrientationIsLandscape(deviceOrientation) && !self.appDelegate.isShowingLandscapeView)
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Landscape" bundle:[NSBundle mainBundle]];
    SearchViewController * landscape = [storyboard instantiateViewControllerWithIdentifier:@"SearchViewController-Landscape"];
    self.appDelegate.isShowingLandscapeView = YES;
    [UIView transitionWithView:landscape.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
        NSMutableArray * viewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
        if (viewControllers && [viewControllers count] > 0)
        {
            for (NSUInteger index = 0; index < [viewControllers count]; index++)
            {
                if ([[[viewControllers objectAtIndex:index] view] tag] == 1000)
                {
                    RootViewController * root = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController-Landscape"];
                    [viewControllers replaceObjectAtIndex:index withObject:root];
                }
                else if ([[[viewControllers objectAtIndex:index] view] tag] == 2000)
                {
                    [viewControllers replaceObjectAtIndex:index withObject:landscape];
                }
            }

            [self.navigationController setViewControllers:viewControllers];
        }
    } completion:NULL];
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) && self.appDelegate.isShowingLandscapeView)
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Portrait" bundle:[NSBundle mainBundle]];
    SearchViewController * portrait = [storyboard instantiateViewControllerWithIdentifier:@"SearchViewController"];
    self.appDelegate.isShowingLandscapeView = NO;
    [UIView transitionWithView:portrait.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
        NSMutableArray * viewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
        if (viewControllers && [viewControllers count] > 0)
        {
            for (NSUInteger index = 0; index < [viewControllers count]; index++)
            {
                if ([[[viewControllers objectAtIndex:index] view] tag] == 1000)
                {
                    RootViewController * root = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController"];
                    [viewControllers replaceObjectAtIndex:index withObject:root];
                }
                else if ([[[viewControllers objectAtIndex:index] view] tag] == 2000)
                {
                    [viewControllers replaceObjectAtIndex:index withObject:portrait];
                }
            }

            [self.navigationController setViewControllers:viewControllers];
        }
    } completion:NULL];
}

コードを拡張して、ナビゲーション コントローラーのネストされたビューでこれを機能させる方法を示しました。ルート ビュー コントローラーで作業している場合は、明らかにすべてのビュー コントローラーをループする必要はありません。インデックス 0 のビュー コントローラーを置き換えるだけです。

これが誰かを助けることを願っています!

于 2012-12-12T08:38:12.187 に答える
0

portait ビュー コントローラーを通常のビューに変更します (ビュー コントローラーから取り出します)。これで、UIView としてインスタンス化して、複数のビュー コントローラーに関連付けられていることを気にせずに遷移を実行できるはずです。

于 2012-12-11T19:02:39.450 に答える