iOS Storyboards: Analyse der Vor- und Nachteile, Best Practices



Apple hat Storyboards erstellt, damit Entwickler die Bildschirme von iOS-Anwendungen und die Beziehungen zwischen ihnen visualisieren können. Nicht jeder mochte dieses Tool und das aus gutem Grund. Ich habe viele Artikel getroffen, in denen Storyboards kritisiert wurden, aber ich habe keine detaillierte und unvoreingenommene Analyse aller Vor- und Nachteile unter Berücksichtigung von Best Practices gefunden. Am Ende habe ich beschlossen, einen solchen Artikel selbst zu schreiben.

Ich werde versuchen, die Nachteile und Vorteile der Verwendung von Storyboards im Detail zu analysieren. Nachdem Sie sie gewogen haben, können Sie eine aussagekräftige Entscheidung treffen, ob sie im Projekt benötigt werden oder nicht. Diese Entscheidung muss nicht radikal sein. Wenn Storyboards in bestimmten Situationen Probleme verursachen, ist ihre Verwendung in anderen gerechtfertigt: Sie hilft, Aufgaben effektiv zu lösen und einfachen, leicht zu wartenden Code zu schreiben.

Beginnen wir mit den Mängeln und analysieren, ob alle noch relevant sind.

Nachteile


1. Storyboards haben Schwierigkeiten, Konflikte beim Zusammenführen von Änderungen zu verwalten


Storyboard ist eine XML-Datei. Es ist weniger lesbar als Code, daher ist es schwieriger, Konflikte darin zu lösen. Diese Komplexität hängt aber auch davon ab, wie wir mit dem Storyboard arbeiten. Sie können Ihre Aufgabe erheblich vereinfachen, wenn Sie die folgenden Regeln befolgen:

  • Platzieren Sie nicht die gesamte Benutzeroberfläche in einem einzigen Storyboard, sondern teilen Sie sie in mehrere kleinere auf. Auf diese Weise können Sie die Arbeit an Storyboards ohne das Risiko von Konflikten auf Entwickler verteilen und im Falle ihrer Unvermeidlichkeit die Lösung vereinfachen.
  • Wenn Sie dieselbe Ansicht an mehreren Stellen verwenden müssen, wählen Sie sie in einer separaten Unterklasse mit einer eigenen Xib-Datei aus.
  • Machen Sie häufiger Commits, da es viel einfacher ist, mit Änderungen in kleinen Stücken zu arbeiten.

Die Verwendung mehrerer Storyboards anstelle von einem macht es uns unmöglich, die gesamte Karte der Anwendung in einer Datei zu sehen. Aber oft ist dies nicht notwendig - nur der spezifische Teil, an dem wir gerade arbeiten, reicht aus.

2. Storyboards verhindern die Wiederverwendung von Code


Wenn wir im Projekt nur Storyboards ohne Xibs verwenden, treten mit Sicherheit Probleme auf. Allerdings sind Xibs meiner Meinung nach notwendige Elemente bei der Arbeit mit Storyboards. Dank ihnen können Sie problemlos wiederverwendbare Ansichten erstellen, mit denen Sie auch bequem im Code arbeiten können.

Erstellen Sie zunächst die Basis- XibView Klasse, die für das Rendern der in Xib erstellten UIView im Storyboard verantwortlich ist:

 @IBDesignable class XibView: UIView { var contentView: UIView? } 

XibView lädt das UIView von Xib in das contentView und fügt es als Unteransicht hinzu. Wir machen das in der setup() Methode:

 private func setup() { guard let view = loadViewFromNib() else { return } view.frame = bounds view.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(view) contentView = view } 

Die loadViewFromNib() -Methode sieht folgendermaßen aus:

 private func loadViewFromNib() -> UIView? { let nibName = String(describing: type(of: self)) let nib = UINib(nibName: nibName, bundle: Bundle(for: XibView.self)) return nib.instantiate(withOwner: self, options: nil).first as? UIView } 

Die setup() -Methode sollte in Initialisierern aufgerufen werden:

 override init(frame: CGRect) { super.init(frame: frame) setup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() } 

Die XibView Klasse XibView bereit. Wiederverwendete Ansichten, deren Erscheinungsbild in einer Xib-Datei gerendert wird, werden von XibView geerbt:

 final class RedView: XibView { } 


Wenn Sie dem Storyboard jetzt eine neue UIView hinzufügen und deren Klasse auf RedView , wird alles erfolgreich angezeigt:

Das Erstellen einer Instanz von RedView im Code erfolgt wie RedView :

 let redView = RedView() 

Ein weiteres nützliches Detail, das nicht jeder kennen kann, ist die Möglichkeit, dem Verzeichnis .xcassets Farben hinzuzufügen . Auf diese Weise können Sie sie global in allen Storyboards und Xibs ändern, in denen sie verwendet werden.

Um Farbe hinzuzufügen, klicken Sie unten links auf „+“ und wählen Sie „Neues Farbset“:

Geben Sie den gewünschten Namen und die gewünschte Farbe an:

Die erstellte Farbe wird im Abschnitt "Benannte Farben" angezeigt:

Darüber hinaus kann es im Code erhalten werden:

 innerView.backgroundColor = UIColor(named: "BackgroundColor") 

3. Sie können keine benutzerdefinierten Initialisierer für in Storyboard erstellte UIViewControllers


Im Fall des Storyboards können wir keine Abhängigkeiten in den Initialisierern der UIViewControllers . Normalerweise sieht es so aus:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.identifier == "detail", let detailVC = segue.destination as? DetailViewController else { return } let object = Object() detailVC.object = object } 

Dieser Code kann besser mit einer Art Konstante erstellt werden, um Bezeichner oder Tools wie SwiftGen und R.swift darzustellen , oder vielleicht sogar Perform . Aber auf diese Weise werden wir nur String-Literale los und fügen syntaktischen Zucker hinzu und lösen nicht die auftretenden Probleme:

  • Woher weiß ich, wie der DetailViewController im obigen Beispiel konfiguriert DetailViewController ? Wenn Sie neu im Projekt sind und nicht über dieses Wissen verfügen, müssen Sie eine Datei mit einer Beschreibung dieses Controllers öffnen und studieren.
  • Die DetailViewController Eigenschaften DetailViewController nach der Initialisierung festgelegt. DetailViewController bedeutet, dass sie optional sein müssen. Es ist erforderlich, Fälle zu behandeln, in denen eine Eigenschaft gleich nil , da die Anwendung sonst im ungünstigsten Moment abstürzen kann. Sie können Eigenschaften als implizit erweitert optional markieren ( var object: Object! ), Aber das Wesentliche ändert sich nicht.
  • Eigenschaften müssen als var markiert sein, nicht let . Eine Situation ist also möglich, wenn jemand von außerhalb sie ändern möchte. DetailViewController sollte mit solchen Situationen umgehen.

Eine Lösung wird in diesem Artikel beschrieben .

4. Wenn das Storyboard wächst, wird die Navigation schwieriger


Wie bereits erwähnt, müssen Sie nicht alles in ein Storyboard einfügen. Es ist besser, es in mehrere kleinere zu unterteilen. Mit dem Aufkommen der Storyboard-Referenz ist es sehr einfach geworden.
Fügen Sie die Storyboard-Referenz aus der Objektbibliothek zum Storyboard hinzu:

Die erforderlichen Feldwerte werden im Attributinspektor festgelegt. Dies ist der Name der Storyboard-Datei und gegebenenfalls die referenzierte ID , die der Storyboard-ID des gewünschten Bildschirms entspricht. Standardmäßig wird der Initial View Controller geladen:

Wenn Sie im Feld Storyboard einen ungültigen Namen angeben oder auf eine nicht vorhandene Storyboard-ID verweisen, werden Sie bei der Kompilierung von Xcode darauf hingewiesen.

5. Xcode wird beim Laden von Storyboards langsamer


Wenn das Storyboard eine große Anzahl von Bildschirmen mit zahlreichen Einschränkungen enthält, dauert das Laden wirklich einige Zeit. Andererseits ist es besser, das große Storyboard in kleinere aufzuteilen. Separat werden sie viel schneller geladen und es wird bequemer, mit ihnen zu arbeiten.

6. Storyboards sind zerbrechlich. Ein Fehler kann dazu führen, dass die Anwendung zur Laufzeit abstürzt


Die Hauptschwächen:

  • Fehler in den UITableViewCell und UICollectionViewCell .
  • Fehler in den Segmentkennungen.
  • Verwenden einer Unterklasse von UIView , die nicht mehr vorhanden ist.
  • Synchronisation von IBActions und IBOutlets mit Code.

All dies und einige andere Probleme können zur Laufzeit zum Absturz der Anwendung führen, was bedeutet, dass solche Fehler wahrscheinlich in den Release-Build fallen. Wenn wir beispielsweise Zellkennungen oder Segmente im Storyboard festlegen, sollten diese überall dort, wo sie verwendet werden, in den Code kopiert werden. Durch Ändern des Bezeichners an einer Stelle muss er an allen anderen Stellen geändert werden. Es besteht die Möglichkeit, dass Sie es einfach vergessen oder einen Tippfehler machen, aber nur während der Ausführung der Anwendung etwas über den Fehler erfahren.

Sie können die Fehlerwahrscheinlichkeit verringern, indem Sie Zeichenfolgenliterale in Ihrem Code entfernen. Zu diesem UICollectionViewCell können den Bezeichnern UITableViewCell und UICollectionViewCell die Namen der UICollectionViewCell selbst zugewiesen werden. Beispielsweise ist der Bezeichner ItemTableViewCell die Zeichenfolge „ItemTableViewCell“. Im Code erhalten wir die Zelle wie folgt:

 let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ItemTableViewCell.self)) as! ItemTableViewCell 

Sie können der UITableView die entsprechende generische Funktion UITableView :

 extension UITableView { open func dequeueReusableCell<T>() -> T where T: UITableViewCell { return dequeueReusableCell(withIdentifier: String(describing: T.self)) as! T } } 

Und dann wird es einfacher, die Zelle zu bekommen:

 let cell: ItemTableViewCell = tableView.dequeueReusableCell() 

Wenn Sie plötzlich vergessen, den Wert der Zellenkennung im Storyboard anzugeben, zeigt Xcode eine Warnung an, sodass Sie diese nicht ignorieren sollten.

Für Segues-IDs können Sie Aufzählungen verwenden. Lassen Sie uns ein spezielles Protokoll erstellen:

 protocol SegueHandler { associatedtype SegueIdentifier: RawRepresentable } 

UIViewController , der dieses Protokoll unterstützt, muss einen verschachtelten Typ mit demselben Namen definieren. Es werden alle UIViewController , die dieser UIViewController kann:

 extension StartViewController: SegueHandler { enum SegueIdentifier: String { case signIn, signUp } } 

Darüber hinaus definieren SegueHandler in der SegueHandler Protokollerweiterung zwei Funktionen: Eine akzeptiert ein UIStoryboardSegue und gibt den entsprechenden SegueIdentifier Wert zurück, und die andere ruft einfach performSegue und nimmt die SegueIdentifier Eingabe:

 extension SegueHandler where Self: UIViewController, SegueIdentifier.RawValue == String { func performSegue(withIdentifier segueIdentifier: SegueIdentifier, sender: AnyObject?) { performSegue(withIdentifier: segueIdentifier.rawValue, sender: sender) } func segueIdentifier(for segue: UIStoryboardSegue) -> SegueIdentifier { guard let identifier = segue.identifier, let identifierCase = SegueIdentifier(rawValue: identifier) else { fatalError("Invalid segue identifier \(String(describing: segue.identifier)).") } return identifierCase } } 

Und jetzt können Sie in einem UIViewController , der das neue Protokoll unterstützt, wie folgt mit prepare(for:sender:) :

 extension StartViewController: SegueHandler { enum SegueIdentifier: String { case signIn, signUp } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segueIdentifier(for: segue) { case .signIn: print("signIn") case .signUp: print("signUp") } } } 

Und laufen Sie wie folgt:

 performSegue(withIdentifier: .signIn, sender: nil) 

Wenn Sie dem SegueIdentifier einen neuen Bezeichner SegueIdentifier , wird Xcode ihn mit Sicherheit zwingen, ihn in switch/case .

Eine andere Möglichkeit, Zeichenfolgenliterale wie Bezeichner-Segues und andere zu entfernen, ist die Verwendung von Tools zur Codegenerierung wie R.swift .

7. Storyboards sind weniger flexibel als Code.


Ja, das ist wahr. Wenn die Aufgabe darin besteht, einen komplexen Bildschirm mit Animationen und Effekten zu erstellen, die das Storyboard nicht verarbeiten kann, müssen Sie den Code verwenden!

8. In Storyboards kann der Typ spezieller UIViewControllers nicht UIViewControllers


Wenn Sie beispielsweise den Typ von UITableViewController in UICollectionViewController UITableViewController UICollectionViewController , müssen Sie das Objekt löschen, ein neues mit einem anderen Typ hinzufügen und es neu konfigurieren. Obwohl dies nicht häufig vorkommt, ist es erwähnenswert, dass solche Änderungen im Code schneller vorgenommen werden.

9. Storyboards fügen dem Projekt zwei zusätzliche Abhängigkeiten hinzu. Sie können Fehler enthalten, die der Entwickler nicht beheben kann.


Dies ist Interface Builder und der Storyboards-Parser. Solche Fälle sind selten und können oft durch andere Lösungen umgangen werden.

10. Anspruchsvolle Codeüberprüfung


Beachten Sie, dass die Codeüberprüfung nicht wirklich eine Fehlersuche ist. Ja, sie werden beim Anzeigen des Codes gefunden, aber das Hauptziel besteht darin, Schwachstellen zu identifizieren, die auf lange Sicht zu Problemen führen können. Bei Storyboards ist dies in erster Linie die Arbeit von Auto Layout . Es sollte keine mehrdeutigen und verlegten geben . Um sie zu finden, verwenden Sie einfach die Suche im Storyboard-XML nach den Zeilen "mehrdeutig =" JA "" und "falsch platziert =" JA "" oder öffnen Sie einfach das Storyboard im Interface Builder und suchen Sie nach roten und gelben Punkten:

Dies reicht jedoch möglicherweise nicht aus. Konflikte zwischen Einschränkungen können auch während der Ausführung der Anwendung erkannt werden. Wenn eine ähnliche Situation auftritt, werden Informationen dazu in der Konsole angezeigt. Solche Fälle sind keine Seltenheit, daher sollte auch ihre Suche ernst genommen werden.

Alles andere - die Anpassung der Position und Größe der Elemente an das Design, die korrekte Bindung von IBOutlets und IBActions - dient nicht der IBOutlets .

Darüber hinaus ist es wichtig, häufiger Commits durchzuführen, damit der Prüfer die Änderungen in kleinen Teilen leichter sehen kann. Er wird besser in der Lage sein, in die Details einzutauchen, ohne etwas zu verpassen. Dies wirkt sich wiederum positiv auf die Qualität der Codeüberprüfung aus.

Zusammenfassung


In der Liste der Storyboard-Fehler habe ich 4 Elemente hinterlassen (in absteigender Reihenfolge ihres Werts):

  1. Storyboards haben Schwierigkeiten, Konflikte beim Zusammenführen von Änderungen zu verwalten.
  2. Storyboards sind weniger flexibel als Code.
  3. Storyboards sind zerbrechlich, ein Fehler kann zur Laufzeit zu einem Absturz führen.
  4. Sie können keine benutzerdefinierten Initialisierer für UIViewControllers die im Storyboard erstellt wurden.

Die Vorteile


1. Visualisierung der Benutzeroberfläche und Einschränkungen


Selbst wenn Sie ein Anfänger sind und gerade ein unbekanntes Projekt gestartet haben, können Sie leicht den Einstiegspunkt in die Anwendung finden und herausfinden, wie Sie von dort aus zum gewünschten Bildschirm gelangen. Sie wissen, wie die einzelnen Schaltflächen, Beschriftungen oder Textfelder aussehen, welche Position sie einnehmen, wie sich Einschränkungen auf sie auswirken und wie sie mit anderen Elementen interagieren. Mit wenigen Klicks können Sie ganz einfach ein neues UIView erstellen und dessen Erscheinungsbild und Verhalten anpassen. Mit dem automatischen Layout können wir natürlich mit UIView , als ob wir gesagt hätten: "Diese Schaltfläche sollte sich links von diesem Etikett befinden und dieselbe Höhe haben." Diese Benutzeroberfläche ist intuitiv und effektiv. Sie können versuchen, Beispiele zu nennen, bei denen gut geschriebener Code beim Erstellen einiger UI-Elemente mehr Zeit spart, aber global ändert sich daran nicht viel. Storyboard macht seinen Job gut.

Beachten Sie separat das automatische Layout. Dies ist ein sehr leistungsfähiges und nützliches Tool, ohne das es schwierig wäre, eine Anwendung zu erstellen, die all die vielen verschiedenen Bildschirmgrößen unterstützt. Mit Interface Builder können Sie das Ergebnis der Arbeit mit Auto Layout anzeigen, ohne die Anwendung zu starten. Wenn einige Einschränkungen nicht in das allgemeine Schema passen, werden Sie von Xcode sofort gewarnt. Natürlich gibt es Fälle, in denen Interface Builder nicht in der Lage ist, das erforderliche Verhalten einer sehr dynamischen und komplexen Schnittstelle bereitzustellen, und Sie sich dann auf den Code verlassen müssen. Aber auch in solchen Situationen können Sie das meiste in Interface Builder tun und es mit nur ein paar Codezeilen ergänzen.

Schauen wir uns einige Beispiele an, die die nützlichen Funktionen von Interface Builder demonstrieren.

Dynamische Tabellen basierend auf UIStackView


Erstellen Sie einen neuen UIViewController und fügen Sie einen UIScrollView Vollbildmodus hinzu:

UIScrollView in UIScrollView eine vertikale UIStackView , UIStackView sie an den Kanten ein und stellen Sie die Höhe und Breite auf UIScrollView . Weisen Sie in dieser Höhe Priorität = Niedrig (250) zu :

Erstellen Sie als Nächstes alle erforderlichen Zellen und fügen Sie sie der UIStackView . Vielleicht ist es gewöhnliches UIView in einer einzigen Kopie oder UIView , für das wir unsere eigene Xib-Datei erstellt haben. In jedem Fall befindet sich die gesamte Benutzeroberfläche dieses Bildschirms im Storyboard. Dank des korrekt konfigurierten automatischen Layouts funktioniert das Scrollen einwandfrei und passt sich dem Inhalt an:



Wir können Zellen auch dazu bringen, sich an die Größe ihres Inhalts anzupassen. Fügen UILabel jeder Zelle UILabel und binden Sie sie an die Kanten:

Es ist bereits klar, wie dies alles zur Laufzeit aussehen wird. Sie können den Zellen beliebige Aktionen hinzufügen, z. B. zu einem anderen Bildschirm wechseln. Und das alles ohne eine einzige Codezeile.
Wenn Sie für eine UIView in einer UIStackView hidden = true UIStackView , wird diese nicht nur UIStackView , sondern nimmt auch keinen Speicherplatz ein. UIStackView berechnet seine Größen automatisch neu:



Selbstleimende Zellen


Setzen Sie im Größeninspektor der Tabelle die Zeilenhöhe = Automatisch und Schätzen auf einen Durchschnittswert:

Damit dies funktioniert, müssen Einschränkungen in den Zellen selbst korrekt konfiguriert sein und eine genaue Berechnung der Zellenhöhe basierend auf dem Inhalt zur Laufzeit ermöglichen. Wenn nicht klar ist, worum es geht, finden Sie in der offiziellen Dokumentation eine sehr gute Erklärung.

Als Ergebnis sehen wir beim Starten der Anwendung, dass alles korrekt angezeigt wird:

Selbstgrößen-Tabelle


Sie müssen dieses Tabellenverhalten implementieren:



Wie erreicht man eine ähnliche dynamische Höhenänderung? Im Gegensatz zu UILabel , UIButton und anderen Unterklassen von UIView ist die Verwendung einer Tabelle etwas schwieriger, da die Größe des intrinsischen Inhalts nicht von der Größe der darin enthaltenen Zellen abhängt. Sie kann ihre Größe nicht anhand des Inhalts berechnen, aber es besteht die Möglichkeit, ihr dabei zu helfen.

Beachten Sie, dass sich die Höhe der Tabelle irgendwann im Video nicht mehr ändert und einen bestimmten Maximalwert erreicht. Dies kann erreicht werden, indem die Tabellenhöhenbeschränkung mit dem Wert Relation = Less Than Or Equal festgelegt wird :

Zu diesem Zeitpunkt weiß der Interface Builder noch nicht, wie hoch die Tabelle sein wird, er kennt nur den Maximalwert von 200 (aus der Höhenbeschränkung). Wie bereits erwähnt, entspricht die intrinsische Inhaltsgröße nicht dem Inhalt der Tabelle. Wir haben jedoch die Möglichkeit, den Platzhalter im Feld Eigengröße festzulegen :

Dieser Wert ist nur gültig, wenn Sie mit Interface Builder arbeiten. Natürlich muss die intrinsische Inhaltsgröße zur Laufzeit nicht diesem Wert entsprechen. Wir haben Interface Builder gerade gesagt, dass alles unter Kontrolle ist.

Erstellen Sie als Nächstes eine neue Unterklasse der CustomTableView Tabelle:

 final class CustomTableView: UITableView { override var contentSize: CGSize { didSet { invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { return contentSize } } 

Einer dieser Fälle, in denen der Code erforderlich ist. Hier rufen wir contentSize invalidateIntrinsicContentSize wenn sich die contentSize der Tabelle ändert. Dadurch kann das System die neue intrinsische Inhaltsgröße akzeptieren. Es gibt wiederum contentSize und zwingt die Tabelle, ihre Höhe dynamisch anzupassen und eine bestimmte Anzahl von Zellen anzuzeigen, ohne zu scrollen. Das Scrollen wird in dem Moment angezeigt, in dem wir die Grenze für die Höhenbeschränkung erreichen.

Alle drei Funktionen des Interface Builder können miteinander kombiniert werden. Sie bieten mehr Flexibilität für die Optionen der UIView ohne dass zusätzliche Einschränkungen oder UIView .

2. Die Fähigkeit, das Ergebnis ihrer Aktionen sofort zu sehen


Wenn Sie die Größe des UIView , ein paar Punkte zur Seite verschoben oder die Hintergrundfarbe geändert haben, sehen Sie sofort, wie es zur Laufzeit aussieht, ohne die Anwendung starten zu müssen. Sie müssen sich nicht wundern, warum eine Schaltfläche nicht auf dem Bildschirm angezeigt wurde oder warum das Verhalten von UIView nicht wie gewünscht ist.

Die Verwendung von @IBInspectable zeigt diesen Vorteil noch interessanter. Fügen Sie UILabel zwei UILabel und zwei Eigenschaften RedView :

 final class RedView: XibView { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var subtitleLabel: UILabel! @IBInspectable var title: String = "" { didSet { titleLabel.text = title } } @IBInspectable var subtitle: String = "" { didSet { subtitleLabel.text = subtitle } } } 

Im Attributinspektor für RedView zwei neue Felder RedView - Title und Subtitle , die wir als @IBInspectable markiert @IBInspectable :

Wenn wir versuchen, Werte in diese Felder einzugeben, sehen wir sofort, wie alles zur Laufzeit aussieht:



Sie können alles steuern: cornerRadius , borderWidth , borderColor . Zum Beispiel erweitern wir die Basisklasse UIView :

 extension UIView { @IBInspectable var cornerRadius: CGFloat { set { layer.cornerRadius = newValue } get { return layer.cornerRadius } } @IBInspectable var borderWidth: CGFloat { set { layer.borderWidth = newValue } get { return layer.borderWidth } } @IBInspectable var borderColor: UIColor? { set { layer.borderColor = newValue?.cgColor } get { return layer.borderColor != nil ? UIColor(cgColor: layer.borderColor!) : nil } } @IBInspectable var rotate: CGFloat { set { transform = CGAffineTransform(rotationAngle: newValue * .pi/180) } get { return 0 } } } 

Wir sehen, dass der Attributes Inspector des RedView Objekts 4 weitere neue Felder RedView , mit denen Sie jetzt auch spielen können:



3. Zeigen Sie alle Bildschirmgrößen gleichzeitig in der Vorschau an


Also haben wir die erforderlichen Elemente auf den Bildschirm geworfen, ihr Erscheinungsbild angepasst und die erforderlichen Einschränkungen hinzugefügt. Wie können wir herausfinden, ob der Inhalt auf verschiedenen Bildschirmgrößen korrekt angezeigt wird? Natürlich können Sie die Anwendung auf jedem Simulator ausführen, aber es wird viel Zeit in Anspruch nehmen. Es gibt eine bessere Option: Xcode verfügt über einen Vorschaumodus, mit dem Sie mehrere Bildschirmgrößen gleichzeitig anzeigen können, ohne die Anwendung zu starten.

Wir rufen den Assistenten-Editor auf , klicken auf das erste Segment der Übergangsleiste und wählen Vorschau -> Einstellungen.Storyboard (als Beispiel):

Zuerst sehen wir nur einen Bildschirm, aber wir können so viel hinzufügen, wie wir brauchen, indem wir in der unteren linken Ecke auf „+“ klicken und die erforderlichen Geräte aus der Liste auswählen:

Wenn das Storyboard mehrere Sprachen unterstützt, können Sie außerdem sehen, wie der ausgewählte Bildschirm mit jeder Sprache aussieht:

Die Sprache kann für alle Bildschirme gleichzeitig und für jeden einzeln ausgewählt werden.

4. Entfernen des Vorlagen-UI-Codes


Das Erstellen einer Benutzeroberfläche ohne Interface Builder wird entweder von einer großen Menge an Boilerplate-Code oder von Superklassen und Erweiterungen begleitet, die zusätzliche Wartungsarbeiten erfordern. Dieser Code kann andere Teile der Anwendung infiltrieren und das Lesen und Suchen erschweren. Durch die Verwendung von Storyboards und Xibs kann Code ausgelagert werden, sodass der Schwerpunkt stärker auf der Logik liegt.

5. Größenklassen


Jedes Jahr erscheinen neue Geräte, für die Sie die Benutzeroberfläche anpassen müssen. Das Konzept der Merkmalsvariationen und insbesondere der Größenklassen , mit denen Sie eine Benutzeroberfläche für jede Größe und Ausrichtung des Bildschirms erstellen können, hilft dabei.

Größenklassen klassifizieren die Höhe (h) und Breite (w) von Gerätebildschirmen in Form von kompakt und regelmäßig ( C und R ). Zum Beispiel hat das iPhone 8 eine Größenklasse (wC hR) im Hochformat und (wC hC) im Querformat , und das iPhone 8 Plus hat (wC hR) bzw. (wR hC) . Die restlichen Geräte finden Sie hier .

In einem Storyboard oder Xib für jede der Größenklassen können Sie Ihren eigenen Datensatz speichern. Die Anwendung verwendet je nach Gerät und Bildschirmausrichtung zur Laufzeit den entsprechenden Datensatz, um die aktuelle Größenklasse zu ermitteln.Wenn einige Layoutparameter für alle Größenklassen gleich sind, können sie in der bereits standardmäßig ausgewählten Kategorie " Beliebig " konfiguriert werden .

Konfigurieren Sie beispielsweise die Schriftgröße abhängig von der Größenklasse. Wir wählen das iPhone 8 Plus-Gerät für die Anzeige im Storyboard im Hochformat aus und fügen eine neue Bedingung hinzu für font: Wenn die Breite Normal ist (setzen Sie alles andere auf „Beliebig“), sollte die Schriftgröße 37 sein:

Wenn wir nun die Bildschirmausrichtung ändern, die Schriftgröße erhöhen - eine neue Bedingung wird funktionieren, da das iPhone 8 Plus im Querformat eine Größenklasse (wR hC) hat . Im Storyboard können Sie je nach Größenklasse auch Ansichten ausblenden, Einschränkungen aktivieren / deaktivieren und deren Wert ändernconstantund vieles mehr. Weitere Informationen darüber , wie all dies zu tun, können Sie lesen hier .

Im obigen Screenshot ist das untere Feld mit der Auswahl des Geräts zur Anzeige des Layouts zu beachten. Sie können damit schnell die Anpassungsfähigkeit der Benutzeroberfläche auf jedem Gerät und bei jeder Bildschirmausrichtung überprüfen und die Größenklasse der aktuellen Konfiguration (neben dem Gerätenamen) anzeigen. Unter anderem befindet sich rechts eine Schaltfläche " Für Eigenschaften variieren" . Ihr Zweck besteht darin, Merkmalsvariationen nur für eine bestimmte Kategorie von Breite, Höhe oder Breite und Höhe gleichzeitig zu ermöglichen. Wenn Sie beispielsweise ein iPad mit einer Größenklasse (wR hR) auswählen , klicken Sie auf „Für Merkmale variieren “ und aktivieren Sie das Kontrollkästchen neben Breite und Höhe. Jetzt gelten alle nachfolgenden Layoutänderungen nur für Geräte mit (wR hR), bis wir auf Done Varying klicken .

Fazit

#
Nachteile
Die Vorteile
1
Schwer zu beherrschende Konflikte
UI-Visualisierung und Einschränkungen
2
Nicht so flexibel wie Code
Die Fähigkeit, das Ergebnis Ihrer Aktionen sofort zu sehen
3
Ein Fehler kann zur Laufzeit zu einem Absturz führen.
Vorschau aller Bildschirmgrößen gleichzeitig
4
Sie können keine benutzerdefinierten Initialisierer verwenden UIViewControllers
Entfernen des Vorlagen-UI-Codes
5
Größenklassen
Wir haben gesehen, dass Storyboards ihre Stärken und Schwächen haben. Meiner Meinung nach sollten Sie die Verwendung nicht vollständig ablehnen. Bei richtiger Anwendung bringen sie große Vorteile und helfen, Aufgaben effektiv zu lösen. Sie müssen nur lernen, wie Sie Argumente wie "Ich mag keine Storyboards" oder "Ich bin es gewohnt, dies zu tun" priorisieren und vergessen.

Source: https://habr.com/ru/post/de456086/


All Articles