web-dev-qa-db-ja.com

iOSで複数のストーリーボードを使用する

私の目的は、タブ付きアプリケーションを作成し、各タブのビューを別々のストーリーボードに構築することです。

Storyboard screenshot

私のメインストーリーボードはタブビューです。

次に、2つのView Controllerを持つセカンダリストーリーボード(ストーリーボード#2)を作成します。最初のView Controller(初期としてもチェックされています)にはボタンがあり、セグエ(モーダル)から2番目のビューがあります。 First view controller

Storyboard#2のloadViewをサブクラス化してオーバーライドすることで、ビューを読み込むことができました。 loadView override

シミュレーターの出力は次のとおりです。

Simulator

[クリックしてください]ボタンをクリックすると、EXC_BAD_ACCESS。セグエは機能せず、2番目のストーリーボードが完全にロードされていないようです。

誰もがこれを前にやろうとして働いたことがありますか? SkillMaster.netからのyoutubeビデオがありますが、セグエがセカンダリストーリーボードの下で機能しているかどうかを示していません。ビデオはこちら: http://youtu.be/D4_twoYvB4M

入力とヘルプをありがとう!

スクリーンショット:

74

これらは、複数のストーリーボードで見た中で最高の記事です。

この男は、コードで新しいストーリーボードを作成する方法を教えてくれるだけでなく、

  • 実際には複数のストーリーボードを推奨しています(よりモジュール化されたコード)
  • xibsとストーリーボードを使用するタイミングについて説明します(xibsはビューを保持し、Storboardはコントローラーに基づいています)
  • ストーリーボードをセグエにリンクするためのクラスを提供します github

複数のストーリーボードの主な欠点は、通常それらをセグエとリンクできないことであるため、この最後のポイントが重要であることに注意してください。

また、説明されている here も参照してください。

79
Rhubarb

OPは質問を編集して回答を含めました。

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"HelpStoryboard" bundle:nil];
UIViewController* initialHelpView = [storyboard instantiateInitialViewController];

initialHelpView.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:initialHelpView animated:YES];

もちろん、これをどこから呼び出すかは意味があります。なぜなら、2つのストーリーボードとそれらのビュースタックがメモリにある可能性があるからです。そのため、他のストーリーボードのView Controllerの外部からこのコードを呼び出すのが最善でしょう。

44
pchap10k

ルバーブが提案した RBStoryboardLink アプローチを検討しました。この実装は、奇妙に見えるView Controllerのプロパティを置き換えます。これを回避する方法を見つけたと思います。 これはデモプロジェクトです

ナビゲーションコントローラー

Navigation Controllerは、参照されるView Controllerをルートとして設定するだけでした。このようなView Controllerの実装は次のようになります。

@interface ExternNavigationController : UINavigationController

@property (strong, nonatomic) NSString *storyboardName;
@property (strong, nonatomic) NSString *sceneIdentifier;

@end

@implementation ExternNavigationController

- (void)awakeFromNib
{
    NSAssert(self.storyboardName, @"storyboardName is required");

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:self.storyboardName bundle:nil];
    UIViewController *vc = self.sceneIdentifier
        ? [storyboard instantiateViewControllerWithIdentifier:self.sceneIdentifier]
        : [storyboard instantiateInitialViewController];

    self.viewControllers = @[vc];
}

@end

ビューコントローラー

外部のストーリーボードで定義されたView Controllerをプッシュするときに問題が発生します。これは、プロパティがコピーされる場合です。これの代わりに、偽の宛先コントローラーを外部のストーリーボードの実際のコントローラーに置き換えるカスタムセグエを実装できます。

@interface ExternStoryboardSegue : UIStoryboardSegue

@end

@implementation ExternStoryboardSegue

- (id)initWithIdentifier:(NSString *)identifier source:(UIViewController *)source destination:(ExternViewController *)destination
{
    NSAssert(destination.storyboardName, @"storyboardName is required");

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:destination.storyboardName bundle:nil];
    UIViewController *vc = destination.sceneIdentifier
        ? [storyboard instantiateViewControllerWithIdentifier:destination.sceneIdentifier]
        : [storyboard instantiateInitialViewController];

    return [super initWithIdentifier:identifier source:source destination:vc];
}

- (void)perform
{
    [[self.sourceViewController navigationController] pushViewController:self.destinationViewController animated:YES];
}

@end

ExternViewControllerはプレースホルダーとして使用され、置換に必要なプロパティ(storyboardNameおよびsceneIdentifier)が含まれています。

@interface ExternViewController : UIViewController

@property (strong, nonatomic) NSString *storyboardName;
@property (strong, nonatomic) NSString *sceneIdentifier;

@end

@implementation ExternViewController

@end

これらのプロパティとプレースホルダービューコントローラーのカスタムクラスを設定する必要があります。また、View ControllerをExternStoryboardSegueとリンクします。

IB screenshot

19
vokilam

XIBファイルの1つから、GUIのより複雑な部分に移動しており、この部分ではストーリーボードを使用しています。そのため、XIBのボタンを使用してストーリーボードに移動します。このために私が持っているコードは次のとおりです。

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"MyStoryboardIdentifier" bundle:nil];
UIViewController* myStoryBoardInitialViewController = [storyboard instantiateInitialViewController];

[self.navigationController pushViewController:myStoryBoardInitialViewController animated:YES];

これにより、StoryBoardがビューに正常にプッシュされます。上記のコードは、ボタン「Touch Up Inside」アクションから呼び出されます。

16

Xcode 7から(およびiOS8に移植されて)、ストーリーボードの参照を使用できるようになりました。これで言及されました WWDC 2015 セッション(最初の1時間くらいでそれらについて話し始めます)。基本的にあなたがしなければならないことは、別々のストーリーボードに移動したいViewControllerを選択し、エディター->ストーリーボードにリファクタリング...をクリックすることです。それに名前と出来上がりを与えます:

enter image description here

新しいストーリーボードに移動されたVCがあり、その外部で参照されていない場合(本来あるべき)、main.storyboardから参照を削除する必要があることに注意してください(それらは新しく作成されたストーリーボードに残ります。それらへの参照のみを削除します)。

9
hris.to

Appleのドキュメントによると、複数のストーリーボードがある場合があります。残念ながら、彼らはそれを行う方法についての本当の詳細には入りません。あなたが知っているように、Interface Builderはあなたを助けませんので、コードでそれをしなければなりません。 XIBをロードするのと同じように機能します。

[UIStoryboard storyboardWithName:@”MyNewStoryboard” bundle:myBundle]

そうは言っても、コメントで言ったように「1つの大きな/肥大化したストーリーボードを望んでいない」なら、XIBが本当に道です。その「大きさ」が利点です。VC間の移行はすべて1か所で行われます。複数のストーリーボードを用意することで、アプリを介した複数の異なる無関係なフローをサポートできます。たとえば、1つのストーリーボードは複雑な構成フロー用で、もう1つはメインユーザーフロー用です。

7
Tim

PerformSegueWithIdenitfierの呼び出しで使用する2番目のストーリーボードに名前付きセグエがある場合、ソースViewControllerの[Identity]タブで[Storyboard ID]フィールドを設定する必要があることがわかりました。

たとえば、VC "ViewController1"という名前のセグエを "segue1"と呼ばれるセグエを別のVCに与えた場合、 "ViewController1"の "ストーリーボードID"を(たとえば "viewC1"または何か)そしてViewController1.mで[self performSegueWithIdentifier:@ "segue1" sender:self]を使用できます。

2
nh32rg

Xcode 8.2.1

外部ストーリーボードでView Controllerを参照できます。

relationship from TabBarController to Storyboard Reference

接続をUITabBarControllerから外部のStoryboard Referenceにドラッグし、「ビューコントローラー」関係として追加します。メインのストーリーボードでは「Item/square」と表示されますが、外部のストーリーボードではUITabBarItemを追加し、タブの名前と画像を定義する必要があります。

enter image description here

Storyboard Referenceが選択されています。

また、外部コントローラーにストーリーボードで「ストーリーボードID」を与える必要があります(ここには表示されていません)、および参照でその名前を参照します。

2
bshirley

このタスクを達成するには、以下の手順に従ってください:

ステップ1Storyboard Referenceコンポーネント(スクリーンショットを参照)

ステップ2:新しいストーリーボード参照を選択します。 (スクリーンショットを参照)

ステップ3:新しいストーリーボード名と初期View Controllerの識別子の識別子を提供します(スクリーンショットを参照)

enter image description here

ビルドして実行します。動作します。

1
Dheeraj D