Verwenden mehrerer Storyboards in iOS

78

Mein Ziel ist es, eine Anwendung mit Registerkarten zu erstellen. Anschließend wird die Ansicht für jede der Registerkarten in separaten Storyboards erstellt.

Storyboard-Screenshot

Mein Hauptstoryboard ist eine Registerkartenansicht.

Dann erstelle ich ein sekundäres Storyboard (Storyboard Nr. 2) mit 2 View Controllern. Der Controller für die erste Ansicht (ebenfalls als initial markiert) verfügt über eine Schaltfläche und wechselt (modal) zur zweiten Ansicht.First View Controller

Ich habe es geschafft, die Ansicht zu laden, indem ich loadView aus Storyboard 2 untergeordnet und überschrieben habe. loadView überschreiben

Hier ist die Simulatorausgabe.

Simulator

Wenn Sie auf die Schaltfläche "Klick mich" klicken, erhalte ich eine EXC_BAD_ACCESS. Der Übergang funktioniert nicht, anscheinend wird das zweite Storyboard nicht vollständig geladen.

Hat jemand schon einmal versucht, dies zu tun und es zum Laufen zu bringen? Es gibt ein Youtube-Video von SkillMaster.net, aber er zeigt nicht, ob ein Segue unter dem sekundären Storyboard funktioniert. Das Video ist hier: http://youtu.be/D4_twoYvB4M

Vielen Dank für jede Eingabe und Hilfe!

Screenshots:

Daddycat Tan Yin See
quelle
20
Ich bin mir nicht sicher, ob dies auch eine gute Praxis ist, aber ich möchte: 1. KEIN großes / aufgeblähtes Storyboard haben 2. Code schwer zusammenführen (wir haben nur wenige Codierer, die arbeiten und
festschreiben
Vielleicht könnten Sie einfach versuchen, die .xib-Dateien zu verwenden, die wir vor iOS5 verwendet haben? Sie sollten nicht zu schwer mit Storyboards zu kombinieren sein.
Tom van der Woerdt
Ich würde gerne wissen, ob wir dazu Storyboard verwenden können. XIB wird definitiv funktionieren.
Daddycat Tan Yin Siehe
5
+1000 für die große Idee der konfliktfreundlichen XML-
Dateiaufteilung
Beim Erstellen einer Produktlinie können mehrere Storyboards sinnvoll sein, nicht das einzelne Produkt. In diesem Fall haben Sie ein Storyboard für das Kern- / Vanilleprodukt und ein Storyboard für jedes angepasste Produkt
Kirill Gamazkov

Antworten:

82

Dies sind die besten Artikel, die ich auf mehreren Storyboards gesehen habe.

Dieser Typ sagt Ihnen nicht nur, wie Sie ein neues Storyboard im Code erstellen, er auch

  • empfiehlt in der Praxis mehrere Storyboards (modularer Code)
  • Erläutert, wann xibs im Vergleich zu Storyboards verwendet werden sollen (xibs enthalten Ansichten, Storboards basieren auf Controllern).
  • bietet eine Klasse zum Verknüpfen von Storyboards mit Segues auf Github

Beachten Sie, dass dieser letzte Punkt wichtig ist, da der Hauptnachteil mehrerer Storyboards darin besteht, dass Sie sie normalerweise nicht mit Segues verknüpfen können, aber die Robs-Bibliothek ermöglicht dies mit ein wenig Fudging

Siehe auch die hier besprochenen

Rhabarber
quelle
44

Das OP hat seine Frage so bearbeitet, dass sie die Antwort enthält:

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

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

Natürlich ist es sinnvoll, woher Sie dies nennen, da Sie möglicherweise zwei Storyboards und deren Ansichtsstapel im Speicher haben. Also wahrscheinlich am besten, wenn Sie diesen Code von außerhalb der View Controller des anderen Storyboards aufrufen.

pchap10k
quelle
2
Diese Frage wurde aus SO entfernt :-(. Auf jeden Fall, wo würden Sie dieses Snippet in diesem Anwendungsfall platzieren? Ich bin mit der gleichen Situation konfrontiert und kann nicht wirklich sehen, wo ich mich UITabbarControllerzum Instanziieren anschließen könnte das richtige Storyboard für jede Registerkarte. Wäre der Delegierte tabBarController:shouldSelectViewController:angemessen?
Jean-Denis Muys
2
Ich verwende den obigen Ansatz, aber nicht mit einer Registerkartenleiste. Ich habe diesen Code in die Aktionsmethode eingefügt, die vom Selektor für die Schaltfläche angegeben wird. Grundsätzlich ist der Code derselbe wie in prepareForSegue, bevor ich die Segued-to-Szene in ein eigenes Storyboard verschoben habe. Ein Fehler, den ich anfangs gemacht habe, war, dass die Hauptansicht meines neuen Storyboards in einen UINavigationController eingebettet war - und nach dem Einrichten habe ich versucht, die Ansicht anstelle des Navigationscontrollers darzustellen.
Rhabarber
19

Ich habe den von Rhabarber vorgeschlagenen RBStoryboardLink- Ansatz untersucht . Diese Implementierung ersetzt die Eigenschaften des View Controllers, was seltsam aussieht. Ich glaube, ich habe den Weg gefunden, dies zu vermeiden. Hier ist das Demo-Projekt .

Navigationssteuerungen

Navigationscontroller können einfach einen referenzierten Ansichtscontroller als Root festlegen. Die Implementierung eines solchen Ansichtscontrollers kann folgendermaßen aussehen:

@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

Controller anzeigen

Probleme beginnen, wenn Sie einen in einem externen Storyboard definierten View Controller verschieben möchten. Dies ist der Fall, wenn Eigenschaften kopiert werden. Stattdessen können wir einen benutzerdefinierten Abschnitt implementieren, der einen gefälschten Zielcontroller durch einen echten aus dem externen Storyboard ersetzt.

@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 wird als Platzhalter verwendet und enthält die für die Ersetzung erforderlichen Eigenschaften (storyboardName und sceneIdentifier).

@interface ExternViewController : UIViewController

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

@end

@implementation ExternViewController

@end

Wir müssen diese Eigenschaften und die benutzerdefinierte Klasse für den Platzhalteransichts-Controller festlegen. Außerdem können Sie den View Controller mit ExternStoryboardSegue verknüpfen.

IB Screenshot

Vokilam
quelle
1
Ich habe versucht, dies mit einer besseren Lösung zu verbessern. Github.com/jeremygrenier/JGLinkedStoryboard
Jeremy Grenier
16

Aus einer meiner XIB-Dateien navigiere ich in einen komplizierteren Teil der GUI und verwende für diesen Teil ein Storyboard. Eine Schaltfläche in meinem XIB navigiert also zum Storyboard. Der Code, den ich dafür habe, ist:

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

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

Dadurch wird mein StoryBoard erfolgreich in die Ansicht verschoben. Der obige Code wird über eine Aktion "Touch Up Inside" aufgerufen.

Joachim H. Skeie
quelle
9

Ab Xcode 7 (und zurück auf iOS8 portiert) können Sie jetzt Storyboard-Referenzen haben. Es wurde in dieser WWDC 2015- Sitzung erwähnt (es beginnt ungefähr in der ersten Stunde darüber zu sprechen). Grundsätzlich mussten Sie nur ViewController auswählen, die Sie in ein separates Storyboard verschieben möchten, und auf Editor-> Refactor to Storyboard ... klicken . Gib ihm einen Namen und voila:

Geben Sie hier die Bildbeschreibung ein

Bitte beachten Sie, dass Sie, wenn Sie VCs hatten, die in das neue Storyboard verschoben wurden und nicht außerhalb des Storyboards referenziert werden (was es sein sollte), deren Referenzen aus main.storyboard löschen sollten (entspannen Sie sich, dass sie im neu erstellten Storyboard verbleiben) nur Verweise auf sie löschen).

hris.to.
quelle
7

Apples Dokumente besagen, dass Sie möglicherweise mehrere Storyboards haben. Leider gehen sie nicht wirklich ins Detail, wie das geht. Wie Sie herausgefunden haben, hilft Ihnen Interface Builder nicht weiter, daher müssen Sie dies im Code tun. Es funktioniert ähnlich wie das Laden von XIBs:

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

Wenn Sie jedoch nicht "ein großes / aufgeblähtes Storyboard wollen", wie Sie in Ihrem Kommentar gesagt haben, sind XIBs wirklich der richtige Weg. Diese „Größe“ ist der Vorteil: Alle Übergänge zwischen VCs sind an einem Ort angeordnet. Wenn Sie mehrere Storyboards haben, können Sie mehrere verschiedene und nicht verwandte Flows über Ihre App unterstützen: Zum Beispiel ein Storyboard für einen komplexen Konfigurationsfluss und ein anderes für den Hauptbenutzerfluss.

Tim
quelle
25
Das größte Problem ist, wenn Sie in einem Team von 3+ arbeiten, in dem das Zusammenführen eines einzelnen Storyboards ein Albtraum ist.
Brian Liang
2
Ich kann mir vorstellen, dass das ein Problem ist. Bei Storyboards gibt es einige Ecken und Kanten. Ihr Punkt ist noch einer.
Tim
4
Sie müssen nicht auf den Komfort von Storyboards verzichten, um Albträume zu vermeiden. Isolieren Sie einfach verschiedene unabhängige Bereiche und weisen Sie jedem ein separates Storyboard zu. Sie haben immer noch die Magie der Storyboards für alle internen Übergänge. Eine Anwendung mit Registerkarten passt perfekt zu diesem Szenario. Ein Einstellungsbildschirm auch. Selbst wenn Sie ein einzelner Entwickler sind, kann es dennoch relevant sein, Ihr Storyboard in mehrere unabhängige Teile aufzuteilen.
KPM
2

Ich habe festgestellt, dass Sie, wenn Sie einen benannten Abschnitt in einem zweiten Storyboard haben, den Sie in einem Aufruf von performSegueWithIdenitfier verwenden möchten, das Feld "Storyboard-ID" auf der Registerkarte "Identität" des Quell-ViewControllers festlegen müssen.

Wenn Sie beispielsweise eine VC mit dem Namen "ViewController1" mit einem Abschnitt namens "segue1" einem anderen VC zugewiesen haben, setzen Sie die "Storyboard-ID" von "ViewController1" auf einen beliebigen Wert (sagen Sie "viewC1" oder so), und dann können Sie dies in ViewController1.m tun Verwenden Sie [self performSegueWithIdentifier: @ "segue1" Absender: self].

nh32rg
quelle
2

Xcode 8.2.1

Sie können auf einen Ansichts-Controller in einem externen Storyboard verweisen.

Beziehung von TabBarController zu Storyboard-Referenz

Ziehen Sie eine Verbindung von der UITabBarControllerzur externen Storyboard-Referenz und fügen Sie sie als "View Controller" -Beziehung hinzu. Im Haupt-Storyboard wird es als "Element / Quadrat" angezeigt, im externen Storyboard sollten Sie jedoch ein hinzufügen UITabBarItemund den Namen und die Bilder für die Registerkarte definieren.

Geben Sie hier die Bildbeschreibung ein

Attributinspektor bei Storyboard ReferenceAuswahl von.

Sie müssen dem externen Controller auch eine "Storyboard-ID" in seinem Storyboard (hier nicht gezeigt) geben und seinen Namen in der Referenz angeben.

bshirley
quelle
1

Führen Sie die folgenden Schritte aus, um diese Aufgabe zu erfüllen:

Schritt 1 : Suchen Sie nach Storyboard ReferenceIn-Komponenten (siehe Screenshot)

Schritt 2 : Wählen Sie eine neue Storyboard-Referenz aus. (Siehe Screenshot)

Schritt 3 : Geben Sie den neuen Storyboard-Namen und die Kennung der Kennung des Controllers für die Erstansicht ein (siehe Screenshot).

Geben Sie hier die Bildbeschreibung ein

Erstellen und ausführen. Es wird klappen.

Dheeraj D.
quelle