Swift bietet einen speziellen Typ namens optionaler Typ. Ein optionaler Typ ist ein Typ, der für einen Wert definiert werden kann, der außergewöhnlich null ist, abgesehen von dem Typ, den er normalerweise hat.
Wenn beispielsweise der Variablen "optionalName", die normalerweise eine Zeichenfolge enthält, in einem speziellen Fall null zugewiesen werden kann, kann die Variable "optionalName" als "Zeichenfolge?" Ausgedrückt werden.
var optionalName: String? = "Brian"
optionalName = nil //Da es sich um einen optionalen String-Typ handelt, kann auch nil zugewiesen werden.
Indem Sie die Zuweisung von nil zulassen, können Sie verhindern, dass die Anwendung abstürzt, auch wenn nil ausnahmsweise in der Variablen enthalten ist, indem Sie eine Nullprüfung mit bedingter Verzweigung durchführen.
var optionalName: String? = "Brian"
optionalName = nil //Da es sich um einen optionalen String-Typ handelt, kann auch nil zugewiesen werden.
if optionalName == nil {
print("Dem Namen wird Nil zugewiesen.")
} else {
print( optionalName! ) //Optionaler Wert, wenn nicht Null!Es ist notwendig, den Wert mit anzugeben
}
Wie oben erwähnt, gibt es eine Möglichkeit zu bestimmen, ob der optionale Typ mit der if-Anweisung Null ist, aber Swift bietet auch ** optionale Bindungssyntax **.
var optionalName: String? = "Brian"
if let name = optionalName {
print( name )
}
Wenn auf diese Weise "optionalName" nicht null ist, wird der Wert "name" zugewiesen und Sie können den bedingten Zweig eingeben. Zu diesem Zeitpunkt ist es auch nicht erforderlich, "Name" anzugeben, da der optionale Wert zum Zeitpunkt der Zuweisung zu "Name" angegeben wird.
Eine ausführlichere Erläuterung von Optional finden Sie hier. Extrem optionaler Swift-Typ [Detaillierte Swift 5th Edition Kapitel 4 Optional](https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-Swift-%E7%AC%AC5%E7%89%88- % E8% 8D% BB% E5% 8E% 9F-% E5% 89% 9B% E5% BF% 97 / dp / 48150407X)
Nehmen wir als Beispiel den Anmelde- / Abmeldevorgang der App, um zu sehen, wann dies in Swift von Vorteil sein kann.
Obwohl es schwierig ist, gehe ich diesmal von einer Anwendung aus, die "Anmeldeansicht" für die Anmeldung, "Inhaltsansicht" nach der Anmeldung und "App-Status" kombiniert, die die Benutzerinformationen enthält, die wie folgt angemeldet sind. ..
Erstens ist AppState. Dies ist eine Klasse, die die Informationen des Benutzers enthält, der sich anmeldet und auf den in jeder Ansicht verwiesen werden soll.
Die Struktur Session
ist als EnvironmentObject definiert.
///Repository-Klasse, in der Benutzerinformationen gespeichert werden
class User: Identifiable {
public var uid: String
public var email: String?
init(uid: String, email: String) {
self.uid = uid
self.email = email
}
}
class AppState: ObservableObject {
//Struktur zum Verwalten des Authentifizierungsstatus
struct Session {
var user: User?
var handler: AuthStateDidChangeListenerHandle? //Objekt, das angemeldete Benutzerinformationen enthält
}
@Published public var session = Session()
}
Als nächstes folgt die Interactor-Klasse, die die Verarbeitung (Anmelden / Abmelden) in Bezug auf die Sitzung übernimmt.
import Firebase
class SessionInteractor {
public var appState: AppState
///Rufen Sie EnvironmentObject von der View-Komponente ab und speichern Sie es in der Klasseneigenschaft
init(appState: AppState) {
self.appState = appState
}
///Der Prozess wird jedes Mal aufgerufen, wenn sich der Anmeldestatus des Benutzers ändert
public func listen() {
self.appState.session.handler = Auth.auth().addStateDidChangeListener { (auth, user) in
//Vorzeitige Rückkehr mit Guard Let Statement
guard let user = user else {
self.appState.session.user = nil
return
}
//Zur Benutzereigenschaft Sitzungstyp hinzugefügt
self.appState.session.user = User(
uid: user.uid,
email: user.email!
)
}
}
///Anmeldevorgang
public func signIn() {
//Anmeldevorgang mit Firebase-Authentifizierung
//Wir hängen FIRAuth-Objekte an, aber eine detaillierte Verarbeitung entfällt.
Auth.auth().signIn(/* [Unterlassung]Melden Sie sich mit der Firebase-Authentifizierung an*/)
}
///Abmeldevorgang
public func signOut() -> Bool {
do {
try Auth.auth().signOut()
self.appState.session.user = nil
return true
} catch {
return false
}
}
}
Als nächstes folgt der Code für jede Ansicht.
import SwiftUI
struct SignInView: View {
@EnvironmentObject var appState: AppState
var body: some View {
VStack() {
TextField("Mail Adresse", text: $email)
SecureField("Passwort", text: $password)
Button(action: self.signIn) {
Text("Anmelden")
}
}
}
///Methode, um sich tatsächlich anzumelden
private func signIn() {
let sessionInteractor = SessionInteractor(appState: self.appState)
let result = sessionInteractor.signIn()
}
}
import SwiftUI
struct ContentView: View {
@EnvironmentObject var appState: AppState
var body: some View {
VStack() {
if let user = self.appState.session.user {
Text("Hallo,\(user.email!)")
Button(action: self.signOut) {
Text("Ausloggen")
}
}
}.onAppear(perform: self.loadUserInfo)
}
//Rufen Sie den Abmeldevorgang auf
private func signOut() {
let sessionInteractor = SessionInteractor(appState: self.appState)
let result = sessionInteractor.signOut()
}
}
Das "User" -Objekt von AppState ist das Herzstück dieser Zeit.
//Struktur zum Verwalten des Authentifizierungsstatus
struct Session {
var user: User? //Eine Struktur mit Benutzerinformationen als Eigenschaft, obwohl die Beschreibung weggelassen wird.
var handler: AuthStateDidChangeListenerHandle? //Objekt, das angemeldete Benutzerinformationen enthält
}
Diese werden als optional definiert, da das Objekt des angemeldeten Benutzers vor dem Anmelden, nach dem Abmelden usw. "Null" ist. Nach der Anmeldung und Eingabe von Benutzerinformationen in das Benutzerobjekt werden diese Informationen in der Ansicht angezeigt.
var body: some View {
VStack() {
if let user = self.appState.session.user {
Text("Hallo,\(user.email!)") // !Anzeigen und Anzeigen in
Button(action: self.signOut) {
Text("Ausloggen")
}
}
}.onAppear(perform: self.loadUserInfo)
}
Was ich hier beachten möchte, ist der Teil, der mit der ** optionalen Bindungssyntax ** verzweigt.
if let user = self.appState.session.user {
Wenn Sie dies schreiben, spielt es keine Rolle, ob das "Benutzer" -Objekt nach dem Abmelden des Benutzers "Null" wird. Im Gegenteil, wenn dies nicht beschrieben wird, erhält die Ansichtsseite die zum Zeitpunkt der Abmeldung zugewiesene Null, und die Anwendung stürzt ab.
Fatal error: Unexpectedly found nil while unwrapping an Optional value
try Auth.auth().signOut()
self.appState.session.user = nil //Benutzerinformationen werden beim Abmelden entfernt
Dieses Mal habe ich das Anmelden / Abmelden als Beispiel genommen, aber ich denke, dass es viele Fälle gibt, in denen mehrere Ansichten beim Erstellen einer mobilen Anwendung auf denselben Wert verweisen. Je mehr Ansichten Sie referenzieren, desto wahrscheinlicher ist es, dass Sie ** unerwartetes Null ** erhalten, was zum Absturz Ihrer App führt. Sie können sie jedoch verhindern, indem Sie den optionalen Typ verwenden. .. Alles sollte nicht optional sein, aber für Eigenschaften und Variablen **, die ** nil zugewiesen werden sollen, verwenden Sie Optional!
Versuchen Sie die Firebase-Authentifizierung unter iOS Extrem optionaler Swift-Typ [Detaillierte Swift 5th Edition Kapitel 4 Optional](https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-Swift-%E7%AC%AC5%E7%89%88- % E8% 8D% BB% E5% 8E% 9F-% E5% 89% 9B% E5% BF% 97 / dp / 48150407X)
Recommended Posts