So wie ich es verstehe, möchten Sie:
- Entwerfen Sie eine Zelle in IB, die in mehreren Storyboard-Szenen verwendet werden kann.
- Konfigurieren Sie eindeutige Storyboard-Abschnitte von dieser Zelle, abhängig von der Szene, in der sich die Zelle befindet.
Leider gibt es derzeit keine Möglichkeit, dies zu tun. Um zu verstehen, warum Ihre vorherigen Versuche nicht funktioniert haben, müssen Sie mehr über die Funktionsweise von Storyboards und Prototyp-Tabellenansichtszellen wissen. (Wenn Sie sich nicht darum kümmern, warum diese anderen Versuche nicht funktioniert haben, können Sie jetzt gehen. Ich habe keine magischen Problemumgehungen für Sie, außer vorzuschlagen, dass Sie einen Fehler melden.)
Ein Storyboard ist im Wesentlichen nicht viel mehr als eine Sammlung von .xib-Dateien. Wenn Sie einen Table View Controller laden, der einige Prototypzellen aus einem Storyboard enthält, geschieht Folgendes:
- Jede Prototypzelle ist tatsächlich eine eigene eingebettete Mini-Feder. Wenn der Table View Controller geladen wird, durchläuft er alle Schreibfedern und Aufrufe der Prototypzelle
-[UITableView registerNib:forCellReuseIdentifier:]
.
- Die Tabellenansicht fragt den Controller nach den Zellen.
- Sie rufen wahrscheinlich an
-[UITableView dequeueReusableCellWithIdentifier:]
Wenn Sie eine Zelle mit einer bestimmten Wiederverwendungskennung anfordern, wird geprüft, ob eine Feder registriert ist. Wenn dies der Fall ist, wird eine Instanz dieser Zelle instanziiert. Dies setzt sich aus folgenden Schritten zusammen:
- Sehen Sie sich die Klasse der Zelle an, wie sie in der Spitze der Zelle definiert ist. Rufen Sie an
[[CellClass alloc] initWithCoder:]
.
- Die
-initWithCoder:
Methode führt Unteransichten durch und legt Eigenschaften fest, die in der Schreibfeder definiert wurden. ( IBOutlet
s werden wahrscheinlich auch hier angeschlossen, obwohl ich das nicht getestet habe; es kann in passieren -awakeFromNib
)
Sie konfigurieren Ihre Zelle, wie Sie möchten.
Wichtig hierbei ist, dass zwischen der Klasse der Zelle und dem visuellen Erscheinungsbild der Zelle unterschieden wird. Sie können zwei separate Prototypzellen derselben Klasse erstellen, deren Unteransichten jedoch völlig unterschiedlich angeordnet sind. Wenn Sie die Standardstile UITableViewCell
verwenden, geschieht genau dies. Der "Standard" -Stil und der "Untertitel" -Stil werden beispielsweise beide von derselben UITableViewCell
Klasse dargestellt.
Dies ist wichtig : Die Klasse der Zelle hat keine Eins-zu-Eins-Korrelation mit einer bestimmten Ansichtshierarchie . Die Ansichtshierarchie wird vollständig durch das bestimmt, was sich in der Prototypzelle befindet, die bei diesem bestimmten Controller registriert wurde.
Beachten Sie auch, dass die Wiederverwendungskennung der Zelle in keiner globalen Zellapotheke registriert wurde. Die Wiederverwendungskennung wird nur im Kontext einer einzelnen UITableView
Instanz verwendet.
Schauen wir uns anhand dieser Informationen an, was bei Ihren obigen Versuchen passiert ist.
Fügen Sie in Controller 1 eine Prototypzelle hinzu, setzen Sie die Klasse auf meine UITableViewCell-Unterklasse, legen Sie die Wiederverwendungs-ID fest, fügen Sie die Beschriftungen hinzu und verdrahten Sie sie mit den Ausgängen der Klasse. Fügen Sie in Controller 2 eine leere Prototypzelle hinzu, setzen Sie sie auf dieselbe Klasse und verwenden Sie die ID wie zuvor wieder. Wenn es ausgeführt wird, werden die Beschriftungen nie angezeigt, wenn die Zellen in Controller 2 angezeigt werden. Funktioniert gut in Controller # 1.
Dies wird erwartet. Während beide Zellen dieselbe Klasse hatten, enthielt die Ansichtshierarchie, die in Controller 2 an die Zelle übergeben wurde, keinerlei Unteransichten. Sie haben also eine leere Zelle, genau das haben Sie in den Prototyp eingefügt.
Entwarf jeden Zelltyp in einer anderen NIB und verdrahtete ihn mit der entsprechenden Zellklasse. Fügen Sie im Storyboard eine leere Prototypzelle hinzu und legen Sie deren Klasse und Wiederverwendungs-ID fest, um auf meine Zellenklasse zu verweisen. Registrieren Sie in den viewDidLoad-Methoden der Controller diese NIB-Dateien für die Wiederverwendungs-ID. Wenn gezeigt, waren die Zellen in beiden Controllern wie der Prototyp leer.
Auch dies wird erwartet. Die Wiederverwendungskennung wird nicht zwischen Storyboard-Szenen oder Schreibfedern geteilt, sodass die Tatsache, dass alle diese unterschiedlichen Zellen dieselbe Wiederverwendungskennung hatten, bedeutungslos war. Die Zelle, die Sie aus der Tabellenansicht zurückerhalten, hat ein Erscheinungsbild, das der Prototypzelle in dieser Szene des Storyboards entspricht.
Diese Lösung war jedoch nah. Wie Sie bereits bemerkt haben, können Sie einfach programmgesteuert aufrufen -[UITableView registerNib:forCellReuseIdentifier:]
und UINib
die Zelle übergeben, und Sie erhalten dieselbe Zelle zurück. (Dies liegt nicht daran, dass der Prototyp die Feder "überschrieben" hat. Sie hatten die Feder einfach nicht in der Tabellenansicht registriert, sodass immer noch die im Storyboard eingebettete Feder angezeigt wurde.) Leider gibt es einen Fehler bei diesem Ansatz - Es gibt keine Möglichkeit, Storyboard-Segmente an eine Zelle in einer eigenständigen Feder anzuschließen.
Bewahrte Prototypen in beiden Controllern leeren und setzen die Klasse und verwenden die ID wieder für meine Zellenklasse. Konstruierte die Benutzeroberfläche der Zellen vollständig in Code. Zellen funktionieren perfekt in allen Controllern.
Natürlich. Hoffentlich ist das nicht überraschend.
Deshalb hat es nicht funktioniert. Sie können Ihre Zellen in eigenständigen Schreibfedern entwerfen und in mehreren Storyboard-Szenen verwenden. Sie können derzeit keine Storyboard-Segmente mit diesen Zellen verbinden. Hoffentlich haben Sie beim Lesen etwas gelernt.
Trotz der großartigen Antwort von BJ Homer habe ich das Gefühl, eine Lösung zu haben. Soweit meine Tests gehen, funktioniert es.
Konzept: Erstellen Sie eine benutzerdefinierte Klasse für die xib-Zelle. Dort können Sie auf ein Touch-Ereignis warten und den Übergang programmgesteuert durchführen. Jetzt brauchen wir nur noch einen Verweis auf den Controller, der den Segue ausführt. Meine Lösung besteht darin, es einzustellen
tableView:cellForRowAtIndexPath:
.Beispiel
Ich habe eine
DetailedTaskCell.xib
mit einer Tabellenzelle, die ich in mehreren Tabellenansichten verwenden möchte:TaskGuessTableCell
Für diese Zelle gibt es eine benutzerdefinierte Klasse :Hier geschieht die Magie.
Ich habe mehrere Segues, aber alle haben den gleichen Namen :
"FinishedTask"
. Wenn Sie hier flexibel sein müssen, schlage ich vor, eine weitere Eigenschaft hinzuzufügen.Der ViewController sieht folgendermaßen aus:
Es gibt vielleicht elegantere Wege, um dasselbe zu erreichen, aber - es funktioniert! :) :)
quelle
-setSelected:
, wenn Sie die Zelle überschreiben und den Übergang nur beim Übergang vonNO
zu auslösenYES
.setSelected:
, BJ. Vielen Dank. In der Tat ist es eine unelegante Lösung (es fühlt sich falsch an), aber gleichzeitig funktioniert es, also benutze ich es, bis dies behoben ist (oder sich etwas in Apples Gericht ändert).Ich habe danach gesucht und diese Antwort von Richard Venable gefunden. Für mich geht das.
quelle
BJ Homer hat eine ausgezeichnete Erklärung gegeben, was los ist.
Aus praktischer Sicht würde ich hinzufügen, dass, da Sie keine Zellen als xibs UND Verbindungssegmente haben können, die Zelle am besten als xib ausgewählt werden kann - Übergänge sind viel einfacher zu pflegen als Zellenlayouts und -eigenschaften an mehreren Stellen und Ihre Segmente unterscheiden sich wahrscheinlich sowieso von Ihren verschiedenen Controllern. Sie können den Übergang direkt von Ihrem Tabellenansichts-Controller zum nächsten Controller definieren und im Code ausführen. .
Ein weiterer Hinweis ist, dass Ihre Zelle als separate xib-Datei verhindert, dass Sie Aktionen usw. direkt mit dem Tabellenansichts-Controller verbinden können (das habe ich sowieso nicht geklärt - Sie können den Eigentümer der Datei nicht als sinnvoll definieren ). Ich arbeite daran, indem ich ein Protokoll definiere, dem der Tabellenansichts-Controller der Zelle entsprechen soll, und den Controller als schwache Eigenschaft, ähnlich einem Delegaten, in cellForRowAtIndexPath hinzufüge.
quelle
Swift 3
BJ Homer gab eine ausgezeichnete Erklärung. Es hilft mir, das Konzept zu verstehen. An
make a custom cell reusable in storyboard
, die in jedem TableViewController verwendet werden können, müssen wir unsmix the Storyboard and xib
nähern. Angenommen, wir haben eine Zelle mit dem NamenCustomCell
, die imTableViewControllerOne
und verwendet werden sollTableViewControllerTwo
. Ich mache es in Schritten.1. Datei> Neu> Klicken Sie auf Datei> Cocoa Touch-Klasse
CustomCell
auswählen > klicken Sie auf Weiter> Geben Sie beispielsweise den Namen Ihrer Klasse an > wählen Sie Unterklasse als UITableVieCell aus> Aktivieren Sie das Kontrollkästchen Auch XIB-Datei erstellen und klicken Sie auf Weiter.2. Passen Sie die Zelle nach Ihren Wünschen an und legen Sie den Bezeichner im Attributinspektor für die Zelle fest. Hier legen wir fest, wie
CellIdentifier
. Diese Kennung wird in Ihrem ViewController verwendet, um die Zelle zu identifizieren und wiederzuverwenden.3. Jetzt müssen wir nur noch
register this cell
in unserem ViewControllerviewDidLoad
. Keine Initialisierungsmethode erforderlich.4. Jetzt können wir diese benutzerdefinierte Zelle in jeder Tabellenansicht verwenden.
In TableViewControllerOne
quelle
Ich habe einen Weg gefunden, die Zelle für dieselbe VC zu laden, die nicht für die Segues getestet wurde. Dies könnte eine Problemumgehung zum Erstellen der Zelle in einer separaten Schreibfeder sein
Angenommen, Sie haben eine VC- und zwei Tabellen und möchten eine Zelle im Storyboard entwerfen und in beiden Tabellen verwenden.
(Beispiel: eine Tabelle und ein Suchfeld mit einem UISearchController mit einer Tabelle für Ergebnisse, und Sie möchten in beiden dieselbe Zelle verwenden.)
Wenn der Controller nach der Zelle fragt, gehen Sie wie folgt vor:
Und hier hast du deine Zelle aus dem Storyboard
quelle
tableView:cellForRowAtIndexPath:
).