Buduję aplikację na iOS za pomocą Storyboard. Kontroler widoku głównego jest kontrolerem paska kart. Tworzę proces logowania / wylogowywania, i to w większości działa dobrze, ale mam kilka problemów. Muszę znać NAJLEPSZY sposób na skonfigurowanie tego wszystkiego.
Chcę wykonać następujące czynności:
- Pokaż ekran logowania przy pierwszym uruchomieniu aplikacji. Po zalogowaniu przejdź do pierwszej karty Kontrolera paska kart.
- Za każdym razem, gdy uruchamiają aplikację, sprawdź, czy są zalogowani i przejdź bezpośrednio do pierwszej karty głównego kontrolera paska kart.
- Kiedy ręcznie klikną przycisk wylogowania, pokaż ekran logowania i usuń wszystkie dane z kontrolerów widoku.
Do tej pory ustawiłem kontroler widoku głównego na kontroler paska kart i utworzyłem niestandardowy segment dla mojego kontrolera widoku logowania. W mojej klasie Tab Bar Controller sprawdzam, czy są zalogowani w viewDidAppear
metodzie, i wykonuję segue:[self performSegueWithIdentifier:@"pushLogin" sender:self];
Ustawiam również powiadomienie, kiedy należy wykonać akcję wylogowania: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutAccount) name:@"logoutAccount" object:nil];
Po wylogowaniu usuwam dane uwierzytelniające z pęku kluczy, uruchamiam [self setSelectedIndex:0]
i wykonuję segue, aby ponownie wyświetlić kontroler widoku logowania.
To wszystko działa dobrze, ale zastanawiam się: czy ta logika powinna być w AppDelegate? Mam również dwa problemy:
- Przy pierwszym uruchomieniu aplikacji kontroler paska kart wyświetla się krótko przed wykonaniem segue. Próbowałem przenieść kod do,
viewWillAppear
ale segue nie zadziała tak wcześnie. - Po wylogowaniu wszystkie dane nadal znajdują się we wszystkich kontrolerach widoku. Jeśli zalogują się na nowe konto, dane starego konta będą nadal wyświetlane, dopóki nie zostaną odświeżone. Potrzebuję sposobu, aby to łatwo usunąć przy wylogowaniu.
Jestem otwarty na przeróbkę tego. Rozważyłem uczynienie ekranu logowania głównym kontrolerem widoku lub utworzenie kontrolera nawigacyjnego w AppDelegate do obsługi wszystkiego ... Po prostu nie jestem pewien, jaka jest najlepsza metoda w tym momencie.
Odpowiedzi:
W appDelegate.m wewnątrz didFinishLaunchingWithOptions
W pliku SignUpViewController.m
W pliku MyTabThreeViewController.m
Wersja Swift 4
didFinishLaunchingWithOptions w delegacie aplikacji, zakładając, że początkowy kontroler widoku jest podpisany w TabbarController.
W widoku kontrolera rejestracji:
MyTabThreeViewController
źródło
AppDelegate
wewnątrzUIViewController
i ustawianiawindow.rootViewController
tam. Nie uważam tego za „najlepszą praktykę”.-1
bez opublikowania odpowiedzi: stackoverflow.com/a/30664935/1226304AppDelegate
wewnątrzUIViewController
-1 do przechowywania klucza logowania wNSUserDefaults
. Jest bardzo niepewny dla tego rodzaju danych!Oto, co zrobiłem, aby wszystko osiągnąć. Jedyną rzeczą, którą musisz wziąć pod uwagę oprócz tego jest (a) proces logowania i (b) gdzie przechowujesz dane aplikacji (w tym przypadku użyłem singletonu).
Jak widać, kontroler widoku głównego jest moim kontrolerem karty głównej . Zrobiłem to, ponieważ po zalogowaniu się użytkownika chcę, aby aplikacja uruchomiła się bezpośrednio na pierwszej karcie. (Pozwala to uniknąć „migotania”, gdy widok logowania pokazuje się tymczasowo).
AppDelegate.m
W tym pliku sprawdzam, czy użytkownik jest już zalogowany. Jeśli nie, pcham kontroler widoku logowania. Zajmuję się także procesem wylogowania, w którym usuwam dane i wyświetlam widok logowania.
LoginViewController.m
Tutaj, jeśli logowanie się powiedzie, po prostu odrzucam widok i wysyłam powiadomienie.
źródło
[self.window makeKeyAndVisible]; [self.window.rootViewController presentViewController:viewController animated:animated completion:nil];
zself.window.rootViewController = viewController;
celu zapobiegania migotania. Aby ożywić, po prostu zawiń go w[UIView transitionWithView...];
EDYCJA: Dodaj akcję wylogowania.
1. Przede wszystkim przygotuj plik delegowany aplikacji
AppDelegate.h
AppDelegate.m
2. Utwórz klasę o nazwie Użytkownik.
Użytkownik. H
Użytkownik.m
3. Utwórz nowy kontroler RootViewController i połączony z pierwszym widokiem, w którym znajduje się przycisk logowania. Dodaj także identyfikator serii ujęć: „initialView”.
RootViewController.h
RootViewController.m
4. Utwórz nowy kontroler LoginViewController i połączony z widokiem logowania.
LoginViewController.h
LoginViewController.m
5. Na koniec dodaj nowy kontroler ProfileViewController i połączony z widokiem profilu w tabViewController.
ProfileViewController.h
ProfileViewController.m
LoginExample to przykładowy projekt zapewniający dodatkową pomoc.
źródło
Nie podobała mi się odpowiedź bhavyi z powodu używania
AppDelegate
wewnątrz kontrolerów widoku, a ustawienierootViewController
nie ma animacji. Odpowiedź Trevora dotyczy problemu z flashowaniem kontrolera widoku na iOS8.UPD 18.07.2015
AppDelegate wewnątrz kontrolerów widoku:
Zmiana stanu (właściwości) AppDelegate w kontrolerze widoku przerywa enkapsulację.
Bardzo prosta hierarchia obiektów w każdym projekcie iOS:
AppDelegate (właściciel
window
irootViewController
)ViewController (właścicielem
view
)Jest ok, że obiekty z góry zmieniają obiekty na dole, ponieważ je tworzą. Ale nie jest ok, jeśli obiekty na dole zmieniają obiekty na nich (opisałem kilka podstawowych zasad programowania / OOP: DIP (Zasada odwrócenia zależności: moduł wysokiego poziomu nie może zależeć od modułu niskiego poziomu, ale powinien zależeć od abstrakcji) ).
Jeśli jakikolwiek obiekt zmieni dowolny obiekt w tej hierarchii, wcześniej czy później w kodzie pojawi się bałagan. W małych projektach może być w porządku, ale nie jest fajnie przekopać się przez ten bałagan w projektach bitowych =]
UPD 18.07.2015
Replikuję animacje kontrolera modalnego za pomocą
UINavigationController
(tl; dr: sprawdź projekt ).Używam
UINavigationController
do prezentacji wszystkich kontrolerów w mojej aplikacji. Początkowo wyświetlałem kontroler widoku logowania na stosie nawigacji z prostą animacją push / pop. Następnie postanowiłem zmienić go na modalny z minimalnymi zmianami.Jak to działa:
Kontroler widoku początkowego (lub
self.window.rootViewController
) jest UINavigationController z ProgressViewController jakorootViewController
. Pokazuję ProgressViewController, ponieważ inicjowanie DataModel może trochę potrwać, ponieważ rozpoczyna on stos danych podstawowych jak w tym artykule (bardzo podoba mi się to podejście).AppDelegate jest odpowiedzialny za uzyskiwanie aktualizacji statusu logowania.
DataModel obsługuje logowanie / wylogowanie użytkownika, a AppDelegate obserwuje jego
userLoggedIn
właściwość za pośrednictwem KVO. Prawdopodobnie nie jest to najlepsza metoda, ale działa dla mnie. (Dlaczego KVO jest złe, możesz sprawdzić w tym lub w tym artykule (część Dlaczego nie korzystać z powiadomień?).ModalDismissAnimator i ModalPresentAnimator służą do dostosowania domyślnej animacji push.
Jak działa logika animatorów:
AppDelegate ustawia się jako delegat
self.window.rootViewController
(który jest UINavigationController).AppDelegate zwraca w
-[AppDelegate navigationController:animationControllerForOperation:fromViewController:toViewController:]
razie potrzeby jednego z animatorów .Animatorzy wdrażają
-transitionDuration:
i-animateTransition:
metody.-[ModalPresentAnimator animateTransition:]
:Projekt testowy jest tutaj .
źródło
AppDelegate
(chciałbym zrozumieć, dlaczego tak robisz) - ale twój komentarz na temat braku animacji jest bardzo poprawny. Można to rozwiązać za pomocą tej odpowiedzi: stackoverflow.com/questions/8053832/...UITabBarController
zbyt długo. Prawdopodobnie zacznę od podejścia do okna zamiast manipulowania kontrolerami widoku.Oto moje rozwiązanie Swifty dla przyszłych obserwatorów.
1) Utwórz protokół do obsługi funkcji logowania i wylogowania:
2) Rozszerz wspomniany protokół i podaj tutaj funkcję wylogowania:
3) Następnie mogę dostosować moją aplikację AppDelegate do protokołu LoginFlowHandler i wywołać
handleLogin
przy starcie:Stąd moje rozszerzenie protokołu zajmie się logiką lub określi, czy użytkownik jest zalogowany / wylogowany, a następnie odpowiednio zmieni rootViewController systemu Windows!
źródło
LoginFlowHandler
. Czy coś brakuje? Zgaduję też, że ten kod zarządza logowaniem tylko podczas uruchamiania. Jak zarządzać wylogowaniem z kontrolera widoku?AppState
implementacja zależy zatem od sposobu zapisywania danych użytkownika na dysku.handleLogout
funkcji?LoginFlowHandler
protokołu. Następnie uzyskasz zasięg, aby móc wywołać metodę handleLogout. Zobacz mój krok 3, aby zobaczyć, jak to zrobiłem dla klasy AppDelegate.Robienie tego z poziomu delegata aplikacji NIE jest zalecane. AppDelegate zarządza cyklem życia aplikacji związanym z uruchamianiem, zawieszaniem, kończeniem i tak dalej. Sugeruję zrobienie tego z początkowego kontrolera widoku w
viewDidAppear
. Możeszself.presentViewController
izself.dismissViewController
kontrolera widoku logowania. Zapiszbool
klucz,NSUserDefaults
aby sprawdzić, czy uruchamia się po raz pierwszy.źródło
Po utworzeniu LoginViewController i TabBarController musimy dodać StoryboardID odpowiednio jako „ loginViewController ” i „ tabBarController ”.
Następnie wolę stworzyć strukturę Constant :
W LoginViewController dodaj IBAction :
W ProfileViewController dodaj IBAction :
W AppDelegate dodaj wiersz kodu w didFinishLaunchingWithOptions :
Na koniec utwórz klasę Switcher :
To wszystko!
źródło
W Xcode 7 możesz mieć wiele storyBoardów. Lepiej będzie, jeśli możesz zachować przepływ logowania w osobnej scenorysie.
Można to zrobić za pomocą WYBIERZ WIDOK KONTROLERA> Edytor> Refaktoryzuj do scenorysu
A oto wersja Swift do ustawiania widoku jako RootViewContoller-
źródło
Używam tego do sprawdzenia pierwszego uruchomienia:
(jeśli użytkownik usunie aplikację i ponownie ją zainstaluje, liczy się to jako pierwsze uruchomienie)
W AppDelegate sprawdzam pierwsze uruchomienie i tworzę kontroler nawigacyjny z ekranami logowania (login i rejestracja), które umieszczam na górze bieżącego okna głównego:
Ponieważ jest to zwykły kontroler widoku, jest on niezależny od reszty aplikacji i możesz po prostu zamknąć kontroler widoku, jeśli nie jest już potrzebny. Możesz również przedstawić widok w ten sposób, jeśli użytkownik ręcznie naciśnie przycisk.
BTW: Zapisuję dane logowania od moich użytkowników w następujący sposób:
Aby się wylogować: przełączyłem się z CoreData (zbyt wolno) i teraz używam NSArrays i NSDictionaries do zarządzania moimi danymi. Wylogowanie oznacza po prostu opróżnienie tych tablic i słowników. Ponadto upewnij się, że ustawiłem moje dane w widoku Widoczność.
Otóż to.
źródło
Jestem w tej samej sytuacji co ty i rozwiązanie, które znalazłem do czyszczenia danych, usuwa wszystkie rzeczy CoreData, na których polegają moje kontrolery widoku, aby narysować informacje. Ale nadal uważałem to podejście za bardzo złe, myślę, że bardziej elegancki sposób można to osiągnąć bez scenorysów i używając tylko kodu do zarządzania przejściami między kontrolerami widoku.
Znalazłem ten projekt w Github, który robi wszystkie te rzeczy tylko za pomocą kodu i jest dość łatwy do zrozumienia. Korzystają z bocznego menu przypominającego Facebooka i zmieniają kontroler widoku centralnego w zależności od tego, czy użytkownik jest zalogowany, czy nie. Gdy użytkownik się
appDelegate
wyloguje, usuwa dane z CoreData i ponownie ustawia główny kontroler widoku na ekran logowania.źródło
Miałem podobny problem do rozwiązania w aplikacji i zastosowałem następującą metodę. Nie korzystałem z powiadomień do obsługi nawigacji.
W aplikacji mam trzy scenorysy.
Moje początkowe scenorysy w aplikacji to scenorysy z ekranem powitalnym. Mam kontroler nawigacyjny jako korzeń loginu i paska zadań, aby obsłużyć nawigację po widoku kontrolera.
Utworzyłem klasę Navigator do obsługi nawigacji w aplikacji i wygląda to tak:
Spójrzmy na możliwe scenariusze:
Ponieważ mam kontroler nawigacji jako root, tworzę instancję kontrolera nawigacji jako kontrolera widoku początkowego.
Spowoduje to usunięcie scenorysu slpash z katalogu głównego okna aplikacji i zastąpienie go scenariuszem logowania.
Z storyboardu logowania, po pomyślnym zalogowaniu użytkownika, zapisuję dane użytkownika w Ustawieniach domyślnych użytkownika i inicjalizuję singleton UserData, aby uzyskać dostęp do szczegółów użytkownika. Następnie storyboard z paskiem Tab jest ładowany za pomocą metody nawigatora.
Teraz użytkownik wylogowuje się z ekranu ustawień na pasku kart. Usuwam wszystkie zapisane dane użytkownika i przechodzę do ekranu logowania.
Gdy użytkownik uruchomi aplikację, ekran powitalny zostanie załadowany. Sprawdzam, czy użytkownik jest zalogowany i uzyskuję dostęp do danych użytkownika z ustawień domyślnych użytkownika. Następnie zainicjuj singleton UserData i wyświetli pasek kart zamiast ekranu logowania.
źródło
Dzięki rozwiązaniu bhavyi. Istnieją dwie odpowiedzi na temat szybkiego, ale nie są one nienaruszone. Zrobiłem to w swift3.Below jest głównym kodem.
W AppDelegate.swift
W SignUpViewController.swift
W funkcji logOutAction
źródło
wprowadź opis zdjęcia tutaj
W aplikacji Delegat.m
}
view controller.m W widoku załadowano
}
Działanie przycisku wylogowania
źródło
NSUserDefaults
jest bardzo niepewne dla tego rodzaju danych!