Ich erstelle eine iOS-App mit einem Storyboard. Der Root View Controller ist ein Tab Bar Controller. Ich erstelle den Anmelde- / Abmeldevorgang und er funktioniert größtenteils einwandfrei, aber ich habe einige Probleme. Ich muss den BESTEN Weg kennen, um all dies einzurichten.
Ich möchte Folgendes erreichen:
- Zeigen Sie beim ersten Start der App einen Anmeldebildschirm an. Wenn sie sich anmelden, wechseln Sie zur ersten Registerkarte des Tab Bar Controllers.
- Überprüfen Sie jedes Mal, wenn sie die App danach starten, ob sie angemeldet sind, und springen Sie direkt zur ersten Registerkarte des Root-Registerkartenleisten-Controllers.
- Wenn sie manuell auf eine Abmeldeschaltfläche klicken, wird der Anmeldebildschirm angezeigt und alle Daten von den Ansichtssteuerungen gelöscht.
Was ich bisher getan habe, ist, den Root-View-Controller auf den Tab Bar Controller zu setzen und einen benutzerdefinierten Übergang zu meinem Login-View-Controller zu erstellen. In meiner Tab Bar Controller-Klasse überprüfe ich, ob sie innerhalb der viewDidAppear
Methode angemeldet sind , und führe die folgenden Schritte aus:[self performSegueWithIdentifier:@"pushLogin" sender:self];
Ich habe auch eine Benachrichtigung eingerichtet, wenn die Abmeldeaktion ausgeführt werden muss: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutAccount) name:@"logoutAccount" object:nil];
Nach dem Abmelden lösche ich die Anmeldeinformationen aus dem Schlüsselbund, führe sie aus [self setSelectedIndex:0]
und führe den Übergang durch, um den Controller für die Anmeldeansicht erneut anzuzeigen.
Das alles funktioniert gut, aber ich frage mich: Sollte diese Logik im AppDelegate sein? Ich habe auch zwei Probleme:
- Beim ersten Start der App wird der Tab Bar Controller kurz vor dem Segue angezeigt. Ich habe versucht, den Code zu verschieben,
viewWillAppear
aber der Übergang wird nicht so früh funktionieren. - Wenn sie sich abmelden, befinden sich alle Daten noch in allen View-Controllern. Wenn sie sich bei einem neuen Konto anmelden, werden die alten Kontodaten weiterhin angezeigt, bis sie aktualisiert werden. Ich brauche eine Möglichkeit, dies beim Abmelden einfach zu löschen.
Ich bin offen dafür, dies zu überarbeiten. Ich habe überlegt, den Anmeldebildschirm zum Root-View-Controller zu machen oder einen Navigations-Controller im AppDelegate zu erstellen, um alles zu handhaben ... Ich bin mir nur nicht sicher, welche Methode derzeit die beste ist.
Antworten:
In Ihrem appDelegate.m in Ihrem didFinishLaunchingWithOptions
In der Datei SignUpViewController.m
In der Datei MyTabThreeViewController.m
Swift 4 Version
didFinishLaunchingWithOptions im App-Delegaten unter der Annahme, dass Ihr anfänglicher Ansichts-Controller der in TabbarController signierte ist.
In Anmeldeansicht Controller:
MyTabThreeViewController
quelle
AppDelegate
InnerenUIViewController
und die Einstellungwindow.rootViewController
dort. Ich betrachte dies nicht als "Best Practice".-1
ohne eine Antwort zu schreibenAppDelegate
innenUIViewController
-1 zum Speichern des AnmeldeschlüsselsNSUserDefaults
. Es ist sehr, sehr unsicher für diese Art von Daten!Folgendes habe ich getan, um alles zu erreichen. Das einzige, was Sie zusätzlich berücksichtigen müssen, ist (a) der Anmeldevorgang und (b) wo Sie Ihre App-Daten speichern (in diesem Fall habe ich einen Singleton verwendet).
Wie Sie sehen können, ist der Root-View-Controller mein Main Tab Controller . Ich habe dies getan, weil ich möchte, dass die App direkt nach dem Anmelden des Benutzers direkt auf der ersten Registerkarte gestartet wird. (Dies vermeidet jegliches "Flackern", bei dem die Anmeldeansicht vorübergehend angezeigt wird.)
AppDelegate.m
In dieser Datei überprüfe ich, ob der Benutzer bereits angemeldet ist. Wenn nicht, drücke ich den Anmeldeansichts-Controller. Ich kümmere mich auch um den Abmeldevorgang, bei dem ich Daten lösche und die Anmeldeansicht anzeige.
LoginViewController.m
Wenn die Anmeldung erfolgreich ist, schließe ich hier einfach die Ansicht und sende eine Benachrichtigung.
quelle
[self.window makeKeyAndVisible]; [self.window.rootViewController presentViewController:viewController animated:animated completion:nil];
durchself.window.rootViewController = viewController;
, um das Flackern zu verhindern. Um das zu animieren, wickeln Sie es einfach in ein[UIView transitionWithView...];
BEARBEITEN: Abmeldeaktion hinzufügen.
1. Bereiten Sie zunächst die App-Delegatendatei vor
AppDelegate.h
AppDelegate.m
2. Erstellen Sie eine Klasse mit dem Namen Benutzer.
User.h
User.m
3. Erstellen Sie einen neuen Controller RootViewController und verbinden Sie ihn mit der ersten Ansicht, in der sich die Anmeldeschaltfläche befindet. Fügen Sie auch eine Storyboard-ID hinzu: "initialView".
RootViewController.h
RootViewController.m
4. Erstellen Sie einen neuen Controller LoginViewController, der mit der Anmeldeansicht verbunden ist.
LoginViewController.h
LoginViewController.m
5. Fügen Sie am Ende einen neuen Controller ProfileViewController hinzu, der mit der Profilansicht im tabViewController verbunden ist.
ProfileViewController.h
ProfileViewController.m
LoginExample ist ein Beispielprojekt für zusätzliche Hilfe.
quelle
Ich mochte die Antwort von bhavya nicht, weil sie
AppDelegate
in View Controllern verwendet wurde und die EinstellungrootViewController
keine Animation enthält. Und Trevors Antwort hat ein Problem mit dem Flashing View Controller unter iOS8.UPD 18.07.2015
AppDelegate in View Controllern:
Durch Ändern des AppDelegate-Status (Eigenschaften) im View Controller wird die Kapselung unterbrochen.
Sehr einfache Objekthierarchie in jedem iOS-Projekt:
AppDelegate (besitzt
window
undrootViewController
)ViewController (besitzt
view
)Es ist in Ordnung, dass Objekte von oben Objekte unten ändern, weil sie sie erstellen. Es ist jedoch nicht in Ordnung, wenn Objekte unten Objekte darüber ändern (ich habe einige grundlegende Programmier- / OOP-Prinzipien beschrieben: DIP (Prinzip der Abhängigkeitsinversion: Das Modul auf hoher Ebene darf nicht vom Modul auf niedriger Ebene abhängen, sondern sollte von Abstraktionen abhängen). ).
Wenn ein Objekt ein Objekt in dieser Hierarchie ändert, wird der Code früher oder später durcheinander geraten. Es mag bei kleinen Projekten in Ordnung sein, aber es macht keinen Spaß, dieses Durcheinander bei den Bit-Projekten zu durchforsten =]
UPD 18.07.2015
Ich repliziere Modal Controller Animationen mit
UINavigationController
(tl; dr: check the project ).Ich verwende
UINavigationController
, um alle Controller in meiner App zu präsentieren. Anfangs habe ich den Login View Controller im Navigationsstapel mit einer einfachen Push / Pop-Animation angezeigt. Dann habe ich beschlossen, es mit minimalen Änderungen auf modal umzustellen.Wie es funktioniert:
Der anfängliche View Controller (oder
self.window.rootViewController
) ist UINavigationController mit ProgressViewController alsrootViewController
. Ich zeige ProgressViewController, da die Initialisierung von DataModel einige Zeit in Anspruch nehmen kann, da es den Kerndatenstapel wie in diesem Artikel enthält (dieser Ansatz gefällt mir sehr gut).AppDelegate ist für das Abrufen von Anmeldestatusaktualisierungen verantwortlich.
DataModel übernimmt die Benutzeranmeldung / -abmeldung und AppDelegate beobachtet seine
userLoggedIn
Eigenschaft über KVO. Wohl nicht die beste Methode, aber das funktioniert bei mir. (Warum KVO schlecht ist, können Sie in diesem oder diesem Artikel nachlesen (Warum nicht Benachrichtigungen verwenden? Teil).ModalDismissAnimator und ModalPresentAnimator werden verwendet, um die Standard-Push-Animation anzupassen.
So funktioniert die Animatorlogik:
AppDelegate legt sich als Delegat von fest
self.window.rootViewController
(dies ist UINavigationController).AppDelegate gibt
-[AppDelegate navigationController:animationControllerForOperation:fromViewController:toViewController:]
bei Bedarf einen der Animatoren zurück .Animatoren implementieren
-transitionDuration:
und-animateTransition:
Methoden.-[ModalPresentAnimator animateTransition:]
::Testprojekt ist da .
quelle
AppDelegate
(ich würde gerne verstehen, warum Sie dies tun) - aber Ihr Kommentar zum Mangel an Animation ist sehr gültig. Das kann durch diese Antwort gelöst werden: stackoverflow.com/questions/8053832/…UITabBarController
habe. Ich würde wahrscheinlich mit dem Fensteransatz beginnen, anstatt die Ansichtssteuerungen zu manipulieren.Hier ist meine Swifty-Lösung für alle zukünftigen Zuschauer.
1) Erstellen Sie ein Protokoll für die Anmelde- und Abmeldefunktionen:
2) Erweitern Sie das Protokoll und stellen Sie hier die Funktionen zum Abmelden bereit:
3) Dann kann ich mein AppDelegate an das LoginFlowHandler-Protokoll anpassen und
handleLogin
beim Start Folgendes aufrufen :Von hier aus übernimmt meine Protokollerweiterung die Logik oder bestimmt, ob der Benutzer angemeldet / abgemeldet ist, und ändert dann den Windows-RootViewController entsprechend!
quelle
LoginFlowHandler
. Vermisse ich etwas Ich vermute auch, dass dieser Code die Anmeldung nur beim Start verwaltet. Wie verwalte ich die Abmeldung von einem View Controller?AppState
Implementierung hängt daher davon ab, wie Sie Ihre Benutzerdaten auf der Festplatte speichern.handleLogout
Funktionalität nutzen?LoginFlowHandler
Protokoll anpassen . Anschließend erhalten Sie einen Bereich, in dem Sie die handleLogout-Methode aufrufen können. In Schritt 3 finden Sie ein Beispiel dafür, wie ich das für die AppDelegate-Klasse gemacht habe.Dies vom App-Delegaten aus zu tun, wird NICHT empfohlen. AppDelegate verwaltet den App-Lebenszyklus, der sich auf das Starten, Anhalten, Beenden usw. bezieht. Ich schlage vor, dies von Ihrem anfänglichen View-Controller in der zu tun
viewDidAppear
. Sie könnenself.presentViewController
undself.dismissViewController
von der Anmeldeansicht Controller. Speichern Sie einenbool
Schlüssel,NSUserDefaults
um festzustellen, ob er zum ersten Mal gestartet wird.quelle
Nach dem Erstellen des LoginViewController und des TabBarControllers müssen wir eine StoryboardID als " loginViewController " bzw. " tabBarController " hinzufügen .
Dann ziehe ich es vor, die Konstantenstruktur zu erstellen :
In LoginViewController hinzufügen IBAction :
In ProfileViewController hinzufügen IBAction :
In AppDelegate Codezeilen in hinzufügen didFinishLaunchingWithOptions :
Erstellen Sie schließlich die Switcher- Klasse:
Das ist alles!
quelle
In Xcode 7 können Sie mehrere StoryBoards haben. Es ist besser, wenn Sie den Anmeldefluss in einem separaten Storyboard halten können.
Dies kann mit SELECT VIEWCONTROLLER> Editor> Refactor to Storyboard erfolgen
Und hier ist die Swift-Version zum Festlegen einer Ansicht als RootViewContoller-
quelle
Ich benutze dies, um nach dem ersten Start zu suchen:
(Wenn der Benutzer die App löscht und neu installiert, zählt dies wie ein erster Start.)
Im AppDelegate überprüfe ich den ersten Start und erstelle einen Navigations-Controller mit den Anmeldebildschirmen (Anmelden und Registrieren), die ich über das aktuelle Hauptfenster lege:
Da dies über dem normalen Ansichts-Controller liegt, ist es unabhängig vom Rest Ihrer App und Sie können den Ansichts-Controller einfach schließen, wenn Sie ihn nicht mehr benötigen. Auf diese Weise können Sie die Ansicht auch darstellen, wenn der Benutzer eine Taste manuell drückt.
Übrigens: Ich speichere die Login-Daten meiner Benutzer folgendermaßen:
Für die Abmeldung: Ich habe mich von CoreData entfernt (zu langsam) und verwende jetzt NSArrays und NSDictionaries, um meine Daten zu verwalten. Abmelden bedeutet nur, diese Arrays und Wörterbücher zu leeren. Außerdem stelle ich sicher, dass meine Daten in viewWillAppear festgelegt sind.
Das ist es.
quelle
Ich bin in der gleichen Situation wie Sie und die Lösung, die ich zum Bereinigen der Daten gefunden habe, besteht darin, alle CoreData-Inhalte zu löschen, auf die sich meine View-Controller verlassen, um ihre Informationen zu zeichnen. Aber ich fand diesen Ansatz immer noch sehr schlecht. Ich denke, dass ein eleganterer Weg, dies zu tun, ohne Storyboards und nur mit Code zum Verwalten der Übergänge zwischen Ansichts-Controllern erreicht werden kann.
Ich habe dieses Projekt bei Github gefunden, das all diese Dinge nur per Code erledigt und ziemlich einfach zu verstehen ist. Sie verwenden ein Facebook-ähnliches Seitenmenü und ändern den Controller für die mittlere Ansicht, je nachdem, ob der Benutzer angemeldet ist oder nicht. Wenn sich der Benutzer abmeldet, werden die
appDelegate
Daten aus CoreData entfernt und der Hauptansichts-Controller erneut auf den Anmeldebildschirm gesetzt.quelle
Ich hatte ein ähnliches Problem in einer App zu lösen und habe die folgende Methode verwendet. Ich habe keine Benachrichtigungen für die Navigation verwendet.
Ich habe drei Storyboards in der App.
Mein erstes Storyboard in der App ist das Splash Screen Storyboard. Ich habe den Navigations-Controller als Stamm des Logins für Login und Registerkartenleiste, um die Navigation des View-Controllers zu verwalten.
Ich habe eine Navigator-Klasse für die App-Navigation erstellt und sie sieht folgendermaßen aus:
Schauen wir uns die möglichen Szenarien an:
Da ich den Navigationscontroller als Root habe, instanziiere ich den Navigationscontroller als anfänglichen Ansichtscontroller.
Dadurch wird das Slpash-Storyboard aus dem Stammverzeichnis des App-Fensters entfernt und durch das Login-Storyboard ersetzt.
Wenn der Benutzer im Login-Storyboard erfolgreich angemeldet ist, speichere ich die Benutzerdaten in den Benutzerstandards und initialisiere einen UserData-Singleton, um auf die Benutzerdetails zuzugreifen. Anschließend wird das Storyboard der Registerkartenleiste mithilfe der Navigatormethode geladen.
Jetzt meldet sich der Benutzer vom Einstellungsbildschirm in der Registerkartenleiste ab. Ich lösche alle gespeicherten Benutzerdaten und navigiere zum Anmeldebildschirm.
Wenn der Benutzer die App startet, wird der Begrüßungsbildschirm geladen. Ich überprüfe, ob der Benutzer angemeldet ist und greife über die Standardeinstellungen auf die Benutzerdaten zu. Initialisieren Sie dann den UserData-Singleton und zeigen Sie die Registerkartenleiste anstelle des Anmeldebildschirms an.
quelle
Vielen Dank an Bhavyas Lösung. Es gab zwei Antworten zu Swift, aber diese sind nicht sehr intakt. Ich habe das im swift3 gemacht. Unten ist der Hauptcode.
In AppDelegate.swift
In SignUpViewController.swift
In der logOutAction-Funktion
quelle
Geben Sie hier die Bildbeschreibung ein
In App Delegate.m
}}
view controller.m In view wurde geladen
}}
In der Abmeldeschaltflächenaktion
quelle
NSUserDefaults
ist für diese Art von Daten sehr, sehr unsicher!