In diesem Tutorial erfahren Sie, wie Sie UI-Anwendungen mit View planen und wie Sie
Statusvariablen zum Ändern von UIs verwenden.
Geschätzte Lesezeit: 25 Minuten.
Mit SwiftUI können wir Interface Builder (IB) und Storyboards komplett vergessen. IB und Xcode waren vor Xcode 4 separate Anwendungen, aber das „Andocken“ zwischen ihnen ist immer noch sichtbar, wenn wir den Namen IBAction oder IBOutlet bearbeiten und unsere Anwendung abstürzt, sodass IB nichts über Änderungen im Code weiß. Oder wenn wir Bezeichner für Segues oder für Tabellenzellen festlegen, Xcode sie jedoch nicht überprüfen kann, da es sich um Zeichenfolgen handelt.
SwiftUI zur Rettung! Wir sehen die Änderungen sofort in der Ansicht, sobald wir den Code eingeben. Änderungen auf der einen Seite führen zu einer Aktualisierung auf der anderen Seite, sodass sie immer miteinander verbunden sind. Es gibt keine Zeichenfolgenbezeichner, die falsch sein könnten. Und das ist der gesamte Code, aber er ist viel kleiner als wenn wir ihn mit UIKit geschrieben hätten, sodass es einfacher ist, ihn zu verstehen, zu bearbeiten und zu debuggen. Sag mir, ist das nicht wunderbar?
Lass uns gehen
Beginnen wir ein neues Projekt im Xcode-Projekt (
Shift-Command-N ), wählen Sie
iOS ▸ Single View App , rufen Sie RGBullsEye auf und wählen Sie
SwiftUI als Schnittstelle.
Jetzt ist
AppDelegate.swift in zwei Dateien aufgeteilt:
AppDelegate.swift und SceneDelegate.swift , und SceneDelegate enthält ein Fenster:
SceneDelegate ist mit Ausnahme dieser Zeile fast nicht mit SwiftUI verwandt:
window.rootViewController = UIHostingController(rootView: ContentView())
UIHostingController erstellt einen Ansichtscontroller für SwiftUI-view
ContentView .
Hinweis: Mit UIHostingController können wir SwiftUI-view in eine vorhandene Anwendung integrieren. Fügen Sie den Hosting View Controller zu unserem Storyboard hinzu und erstellen Sie einen Übergang vom UIViewController. Dann verwenden wir Control-Drag mit Segue auf den View-Controller-Code, um eine IBSegueAction zu erstellen, in der wir den Hosting-Controller auf rootView - SwiftUI-view setzen.
Beim Start der Anwendung wird im Fenster eine Instanz von
ContentView angezeigt , die in der Datei
ContentView.swift definiert ist . Dies ist eine
Struktur , die dem
View- Protokoll entspricht:
struct ContentView: View { var body: some View { Text("Hello World") } }
Dies ist eine SwiftUI-Deklaration des Inhalts einer ContentView (
body ). Es gibt jetzt eine Textansicht mit dem Text Hello World.
Direkt unter ContentView_Previews wird eine Instanz von ContentView zurückgegeben.
struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
Hier können wir die Testdaten für die Vorschau einstellen. Aber wo genau ist diese Vorschau?
Unmittelbar nach dem Code befindet sich ein großer leerer Bereich mit dem oben genannten:

Klicken Sie auf
Fortsetzen , warten Sie einen Moment und ...

Skizzieren Sie unsere Benutzeroberfläche
Etwas Vertrautes ist nicht sichtbar - dies ist die Datei
Main.storyboard . Wir werden unsere Benutzeroberfläche mit SwiftUI direkt im Code erstellen, während wir uns die Vorschau ansehen: Was bekommen wir dort? Aber keine Sorge, wir müssen nicht Hunderte von Codezeilen schreiben, um unsere Ansichten zu erstellen.
SwiftUI ist deklarativ: Sie geben an, wie Ihre Benutzeroberfläche aussehen soll, und SwiftUI konvertiert all dies in effizienten Code, der die ganze Arbeit erledigt. Mit Apple können Sie so viele Ansichten wie nötig erstellen, damit der Code einfach und unkompliziert ist. Wiederverwendbare Ansichten mit Parametern werden besonders empfohlen - dies ähnelt der Zuordnung von Code zu einer separaten Funktion. Sie werden es später selbst tun.
Unsere Anwendung wird viele Ansichten haben, daher skizzieren wir zunächst Textansichten als Stubs.
Ersetzen Sie Text ("Hallo Welt") durch:
Text("Target Color Block")
Klicken Sie ggf. auf
Fortsetzen , um die Vorschau zu aktualisieren.
Klicken Sie nun
bei gedrückter Befehlstaste auf diese Ansicht in der
Vorschau und wählen Sie
In HStack einbetten :

Bitte beachten Sie, dass sich auch Ihr Code geändert hat:
HStack { Text("Target Color Block") }
Kopieren Sie den Textoperator, fügen Sie ihn ein und bearbeiten Sie ihn in unserem HStack. Bitte beachten Sie: Wir trennen die Operatoren nicht durch ein Komma, sondern schreiben sie jeweils in eine neue Zeile:
HStack { Text("Target Color Block") Text("Guess Color Block") }
Und so sieht es in der Vorschau aus:
Bereiten wir nun einen Platz für die Slider-Stubs vor, indem wir den
HStack auf
VStack platzieren . Dieses Mal werden wir
Command-Click auf den HStack
in unserem Code machen :

Wählen Sie
In VStack einbetten . Ein neuer Code wird angezeigt, die Vorschau ändert sich jedoch nicht. Wenig später werden wir die Ansicht unter zukünftigen Farbblöcken hinzufügen.
Fügen Sie unmittelbar nach dem HStack eine neue Zeile hinzu, klicken Sie auf
+ in der Symbolleiste, um die Bibliothek zu öffnen, und ziehen Sie den
vertikalen Stapel auf eine neue Zeile:

Wie erwartet haben sich sowohl der Code als auch die Vorschau geändert:

Beenden Sie die Arbeit an der Entwurfs-Benutzeroberfläche, damit alles so aussieht:
VStack { HStack { Text("Target Color Block") Text("Guess Color Block") } Text("Hit me button") VStack { Text("Red slider") Text("Green slider") Text("Blue slider") } }
Im neuen VStack werden etwas später drei Schieberegler sowie eine Schaltfläche zwischen den Schiebereglern und den Farbblöcken angezeigt.
Wir arbeiten weiter an der Benutzeroberfläche
Lassen Sie uns nun in SwiftUI üben, einen HStack mit farbigen Blöcken zu füllen:
HStack {
Jeder Farbblock hat ein Rechteck. Der Zielfarbblock (Ziel) hat eine Textansicht unter dem Rechteck und der ausgewählte (Vermutung) hat drei Textansichten. Wenig später werden wir 'xxx' durch die realen Werte der Schieberegler ersetzen.
Verwenden der Variablen '@State'
In SwiftUI können wir reguläre Variablen verwenden. Wenn sich die Änderung der Variablen jedoch auf die Benutzeroberfläche auswirken soll, markieren wir Variablen wie
'@State' . In unserer Anwendung wählen wir die Farbe aus, sodass alle Variablen, die sich auf die ausgewählte Farbe auswirken, '@ State'-Variablen sind.
Fügen Sie diese Zeilen vor der
Body- Deklaration in die
Struktur ContentView ein :
let rTarget = Double.random(in: 0..<1) let gTarget = Double.random(in: 0..<1) let bTarget = Double.random(in: 0..<1) @State var rGuess: Double @State var gGuess: Double @State var bGuess: Double
Die Werte von R, G und B liegen zwischen 0 und 1. Wir initialisieren die gewünschten Werte mit Zufallswerten. Wir könnten die ausgewählten Werte auch auf 0,5 initialisieren, sie jedoch vorerst nicht initialisieren, um zu zeigen, was in diesem Fall zu tun ist.
Gehen wir etwas tiefer zur
Struktur ContentView_Previews , die die ContentView-Instanz
für die Vorschau initialisiert. Jetzt benötigt der Initialisierer die Anfangswerte der ausgewählten Werte. Ändern Sie
ContentView () wie
folgt :
ContentView(rGuess: 0.5, gGuess: 0.5, bGuess: 0.5)
Wenn wir die Schieberegler erstellen, befinden sich ihre Werte in der Vorschau in der Mitte.
Wir sollten den
Initialisierer auch in
SceneDelegate in der
Szenenfunktion (_: willConnectTo: options :) reparieren -
ContentView () durch Folgendes ersetzen:
window.rootViewController = UIHostingController(rootView: ContentView(rGuess: 0.5, gGuess: 0.5, bGuess: 0.5))
Wenn die Anwendung geladen wird, befinden sich die Schieberegler in der Mitte.
Fügen Sie nun dem Zielrechteck einen Farbmodifikator hinzu:
Rectangle() .foregroundColor(Color(red: rTarget, green: gTarget, blue: bTarget, opacity: 1.0))
Der Modifikator
.foregroundColor erstellt eine neue Rechteckansicht mit der Farbe, die durch zufällig generierte RGB-Werte angegeben wird.
Ändern Sie in ähnlicher Weise das Vermutungsrechteck:
Rectangle() .foregroundColor(Color(red: rGuess, green: gGuess, blue: bGuess, opacity: 1.0))
Mit Werten von R, G und B bei 0,5 erhalten wir eine graue Farbe.
Klicken Sie auf Fortsetzen und warten Sie einen Moment.

Ansicht wiederverwendbar machen
Erstens werden wir nicht über die Wiederverwendung nachdenken und nur einen Schieberegler für Rot erstellen.
Ersetzen Sie in
VStack für Schieberegler den
Textstecker ("Roter Schieberegler") durch diesen
HStack :
HStack { Text("0") .foregroundColor(.red) Slider(value: $rGuess) Text("255") .foregroundColor(.red) }
Wir haben die Textfarbe in der Textansicht rot gemacht. Und sie haben Slider mit einem Standardwert hinzugefügt. Der Standardbereich des Schiebereglers liegt zwischen 0 und 1, was perfekt zu uns passt.
Hinweis: Wir wissen, dass der Schieberegler von 0 bis 1 reicht und die Textbezeichnung "255" lautet, um Benutzern die Darstellung von RGB-Werten im Bereich von 0 bis 255 zu erleichtern.
Aber welche Art von
$ -Symbol hat die Variable? Wissen wir über
? und! bei der arbeit mit
optionalen und jetzt auch
$ ?
Trotz der Tatsache, dass er so klein und unauffällig ist, ist er sehr wichtig.
RGuess selbst ist nur ein schreibgeschützter Wert. Aber
$ rGuess ist eine Bindung . Wir benötigen sie, um das Rechteck der ausgewählten Farbe zu aktualisieren, wenn der Benutzer den Schieberegler bewegt.
Um den Unterschied zu verstehen, legen Sie die Werte für die Drei-Text-Ansicht unter dem vorhersagbaren Rechteck fest:
HStack { Text("R: \(Int(rGuess * 255.0))") Text("G: \(Int(gGuess * 255.0))") Text("B: \(Int(bGuess * 255.0))") }
Hier verwenden wir nur die Werte, ändern sie nicht, daher benötigen wir das Präfix $ nicht.
Warten Sie auf das Vorschau-Update:

Farbige Rechtecke schrumpften leicht, um dem Schieberegler zu entsprechen. Die Textbeschriftungen des Schiebereglers sehen jedoch unordentlich aus - sie sind zu stark an die Ränder gedrückt. Fügen wir HStack - padding einen weiteren Modifikator hinzu:
HStack { Text("0") .foregroundColor(.red) Slider(value: $rGuess) Text("255") .foregroundColor(.red) } .padding()
Jetzt viel besser!
Befehl erstellen
Klicken Sie auf den roten Schieberegler HStack und wählen Sie
Unteransicht extrahieren :

Dies funktioniert genauso wie
Refactor ▸ In Funktion extrahieren, jedoch für die SwiftUI-Ansicht.
An diesem Punkt werden mehrere Fehlermeldungen angezeigt, keine Sorge, jetzt werden wir es beheben.
Benennen Sie die resultierende Ansicht
ColorSlider und fügen Sie diesen Code oben vor dem Hauptteil unserer neuen Ansicht hinzu:
@Binding var value: Double var textColor: Color
Ersetzen Sie nun
$ rGuess durch $ value und .red durch textColor :
Text("0") .foregroundColor(textColor) Slider(value: $value) Text("255") .foregroundColor(textColor)
Kehren wir zur Definition von ColorSlider () in VStack zurück und fügen unsere Parameter hinzu:
ColorSlider(value: $rGuess, textColor: .red)
Stellen Sie sicher, dass die Vorschau mit dem roten Schieberegler in Ordnung ist, und ersetzen Sie die Textstubs durch die grünen und blauen Schieberegler. Vergessen Sie nicht, dort die richtigen Parameter einzugeben:
ColorSlider(value: $gGuess, textColor: .green) ColorSlider(value: $bGuess, textColor: .blue)
Klicken Sie auf
Fortsetzen , um die Vorschau zu aktualisieren:

Hinweis: Möglicherweise haben Sie bemerkt, dass Sie häufig auf Fortsetzen klicken müssen. Wenn Sie Verknüpfungen mögen, werden Sie Option-Command-P wahrscheinlich lieben.
Und jetzt etwas Schönes! Klicken Sie in der unteren rechten Ecke der Vorschau auf die Schaltfläche
Live-Vorschau :

Mit der Live-Vorschau können wir mit der Vorschau interagieren, als ob die Anwendung auf einem Simulator ausgeführt würde!
Versuchen Sie, die Schieberegler zu bewegen:

Großartig! Wir gehen zur letzten Etappe über. Wir wollen doch wissen, wie gut wir die Farbe ausgewählt haben?
Warnung anzeigen
Nachdem die Schieberegler auf die gewünschten Positionen eingestellt wurden, drückt der Benutzer die
Hit Me- Taste. Anschließend wird eine
Warnung mit einer Bewertung angezeigt.
Fügen Sie der ContentView zunächst eine Methode hinzu, um die Punktzahl zu berechnen. Zwischen den Variablen @State und
Körper diese Methode hinzufügen:
func computeScore() -> Int { let rDiff = rGuess - rTarget let gDiff = gGuess - gTarget let bDiff = bGuess - bTarget let diff = sqrt(rDiff * rDiff + gDiff * gDiff + bDiff * bDiff) return Int((1.0 - diff) * 100.0 + 0.5) }
Der
Diff- Wert ist einfach der Abstand zwischen zwei Punkten im dreidimensionalen Raum, dh der Wert des Benutzerfehlers. Um eine Schätzung zu erhalten, subtrahieren Sie diff von 1 und reduzieren Sie dann seinen Wert auf den Bereich 0 - 100. Je kleiner das diff, desto höher die Schätzung.
Ersetzen Sie dann den
Text- Stub
("Hit me button") durch diesen Code:
Button(action: { }) { Text("Hit Me!") }
Button hat Action und Label, wie UIButton. Wir möchten, dass eine Aktion eine Warnansicht auslöst. Wenn wir jedoch eine Warnung in der Aktionsschaltfläche erstellen, geschieht nichts.
Stattdessen machen wir Alert zu einem Teil der ContentView und fügen eine '@State'-Variable vom Typ Bool hinzu. Dann setzen wir diese Variable an der Stelle, an der unser Alert in der Aktionsschaltfläche angezeigt werden soll, auf true. Der Wert wird auf false zurückgesetzt, um die Warnung auszublenden, wenn der Benutzer die Warnung ausblendet.
Fügen Sie diese Variable '@State' hinzu:
@State var showAlert = false
Fügen Sie dann diesen Code als Aktionsschaltfläche hinzu:
self.showAlert = true
Selbst ist für uns notwendig, da showAlert in der Schließung ist.
Fügen Sie zum Schluss den Alert-Modifikator zur Schaltfläche hinzu, damit unsere Schaltfläche ganz wie folgt aussieht:
Button(action: { self.showAlert = true }) { Text("Hit Me!") } .alert(isPresented: $showAlert) { Alert(title: Text("Your Score"), message: Text("\(computeScore())")) }
Wir übergeben $ showAlert als Bindung, da sich der Wert dieser Variablen ändert, sobald der Benutzer die Warnung verbirgt, und diese Änderung dazu führt, dass die Ansicht aktualisiert wird.
SwiftUI verfügt über einen einfachen Initialisierer für die Warnungsansicht. Standardmäßig verfügt es über eine OK-Schaltfläche, sodass wir sie nicht einmal als Parameter festlegen müssen.
Schalten Sie die Live-Vorschau ein, bewegen Sie die Schieberegler und drücken Sie die Taste "Hit me". Voila!

Mit der Live-Vorschau benötigen Sie keinen iOS-Simulator mehr. Obwohl Sie damit Ihre Anwendung horizontal testen können:

Fazit
Hier können Sie den fertigen Publikationsentwurf herunterladen.
In diesem Tutorial wurde SwiftUI nur geringfügig behandelt. Jetzt haben Sie einen Eindruck von den neuen Funktionen von Xcode zum Erstellen von Benutzeroberflächen und Vorschauen sowie von der Verwendung der Variablen "@State" zum Aktualisieren Ihrer Benutzeroberfläche.
Der Einfachheit halber haben wir kein Datenmodell für RGB erstellt. Die meisten Anwendungen erstellen jedoch Modelle ihrer Daten mithilfe von Strukturen oder Klassen. Wenn Sie Änderungen im Modell in SwiftUI verfolgen möchten, muss es dem
ObservableObject- Protokoll entsprechen und die Eigenschaft
willChange implementieren, die Sie über Änderungen
informiert .
Schauen Sie sich Apple-Beispiele und insbesondere den
Datenfluss durch SwiftUI an .
Um SwiftUI verständlicher zu machen, können Sie einer vorhandenen Anwendung eine SwiftUI-Ansicht hinzufügen. Sehen Sie sich Beispiele an, wie Sie dies schnell und einfach tun können.
Siehe
meine Veröffentlichung zur Implementierung von Falt- / Dropdown-Listen mit SwiftUI.
Schließlich studieren Sie die
Dokumentation für SwiftUI , und es gibt wirklich viele nützliche
Dinge !