私の目的は、タブ付きアプリケーションを作成し、各タブのビューを別々のストーリーボードに構築することです。
私のメインストーリーボードはタブビューです。
次に、2つのView Controllerを持つセカンダリストーリーボード(ストーリーボード#2)を作成します。最初のView Controller(初期としてもチェックされています)にはボタンがあり、セグエ(モーダル)から2番目のビューがあります。
Storyboard#2のloadViewをサブクラス化してオーバーライドすることで、ビューを読み込むことができました。
シミュレーターの出力は次のとおりです。
[クリックしてください]ボタンをクリックすると、EXC_BAD_ACCESS
。セグエは機能せず、2番目のストーリーボードが完全にロードされていないようです。
誰もがこれを前にやろうとして働いたことがありますか? SkillMaster.netからのyoutubeビデオがありますが、セグエがセカンダリストーリーボードの下で機能しているかどうかを示していません。ビデオはこちら: http://youtu.be/D4_twoYvB4M
入力とヘルプをありがとう!
スクリーンショット:
これらは、複数のストーリーボードで見た中で最高の記事です。
この男は、コードで新しいストーリーボードを作成する方法を教えてくれるだけでなく、
複数のストーリーボードの主な欠点は、通常それらをセグエとリンクできないことであるため、この最後のポイントが重要であることに注意してください。
また、説明されている here も参照してください。
OPは質問を編集して回答を含めました。
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"HelpStoryboard" bundle:nil];
UIViewController* initialHelpView = [storyboard instantiateInitialViewController];
initialHelpView.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:initialHelpView animated:YES];
もちろん、これをどこから呼び出すかは意味があります。なぜなら、2つのストーリーボードとそれらのビュースタックがメモリにある可能性があるからです。そのため、他のストーリーボードのView Controllerの外部からこのコードを呼び出すのが最善でしょう。
ルバーブが提案した 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とリンクします。
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」アクションから呼び出されます。
Xcode 7から(およびiOS8に移植されて)、ストーリーボードの参照を使用できるようになりました。これで言及されました WWDC 2015 セッション(最初の1時間くらいでそれらについて話し始めます)。基本的にあなたがしなければならないことは、別々のストーリーボードに移動したいViewControllerを選択し、エディター->ストーリーボードにリファクタリング...をクリックすることです。それに名前と出来上がりを与えます:
新しいストーリーボードに移動されたVCがあり、その外部で参照されていない場合(本来あるべき)、main.storyboardから参照を削除する必要があることに注意してください(それらは新しく作成されたストーリーボードに残ります。それらへの参照のみを削除します)。
Appleのドキュメントによると、複数のストーリーボードがある場合があります。残念ながら、彼らはそれを行う方法についての本当の詳細には入りません。あなたが知っているように、Interface Builderはあなたを助けませんので、コードでそれをしなければなりません。 XIBをロードするのと同じように機能します。
[UIStoryboard storyboardWithName:@”MyNewStoryboard” bundle:myBundle]
そうは言っても、コメントで言ったように「1つの大きな/肥大化したストーリーボードを望んでいない」なら、XIBが本当に道です。その「大きさ」が利点です。VC間の移行はすべて1か所で行われます。複数のストーリーボードを用意することで、アプリを介した複数の異なる無関係なフローをサポートできます。たとえば、1つのストーリーボードは複雑な構成フロー用で、もう1つはメインユーザーフロー用です。
PerformSegueWithIdenitfierの呼び出しで使用する2番目のストーリーボードに名前付きセグエがある場合、ソースViewControllerの[Identity]タブで[Storyboard ID]フィールドを設定する必要があることがわかりました。
たとえば、VC "ViewController1"という名前のセグエを "segue1"と呼ばれるセグエを別のVCに与えた場合、 "ViewController1"の "ストーリーボードID"を(たとえば "viewC1"または何か)そしてViewController1.mで[self performSegueWithIdentifier:@ "segue1" sender:self]を使用できます。
外部ストーリーボードでView Controllerを参照できます。
接続をUITabBarController
から外部のStoryboard Referenceにドラッグし、「ビューコントローラー」関係として追加します。メインのストーリーボードでは「Item/square」と表示されますが、外部のストーリーボードではUITabBarItem
を追加し、タブの名前と画像を定義する必要があります。
Storyboard Reference
が選択されています。
また、外部コントローラーにストーリーボードで「ストーリーボードID」を与える必要があります(ここには表示されていません)、および参照でその名前を参照します。