Je crée une application iOS à l'aide d'un Storyboard. Le contrôleur de vue racine est un contrôleur de barre d'onglets. Je crée le processus de connexion / déconnexion, et cela fonctionne généralement bien, mais j'ai quelques problèmes. J'ai besoin de savoir la MEILLEURE façon de mettre tout cela en place.
Je veux accomplir ce qui suit:
- Afficher un écran de connexion lors du premier lancement de l'application. Une fois connecté, accédez au premier onglet du contrôleur de la barre d'onglets.
- Chaque fois qu'ils lancent l'application après cela, vérifiez s'ils sont connectés et passez directement au premier onglet du contrôleur de barre d'onglets racine.
- Lorsqu'ils cliquent manuellement sur un bouton de déconnexion, affichent l'écran de connexion et effacent toutes les données des contrôleurs de vue.
Ce que j'ai fait jusqu'à présent est de définir le contrôleur de vue racine sur le contrôleur de barre d'onglets et de créer un enchaînement personnalisé sur mon contrôleur de vue de connexion. Dans ma classe de contrôleur de barre d'onglets, je vérifie s'ils sont connectés dans la viewDidAppear
méthode et j'effectue la séquence:[self performSegueWithIdentifier:@"pushLogin" sender:self];
J'ai également configuré une notification lorsque l'action de déconnexion doit être effectuée: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutAccount) name:@"logoutAccount" object:nil];
Lors de la déconnexion, j'efface les informations d'identification du trousseau, exécute [self setSelectedIndex:0]
et effectue la séquence pour afficher à nouveau le contrôleur de vue de connexion.
Tout cela fonctionne bien, mais je me demande: cette logique devrait-elle être dans l'AppDelegate? J'ai également deux problèmes:
- La première fois qu'ils lancent l'application , le contrôleur de la barre d'onglets s'affiche brièvement avant la transition. J'ai essayé de déplacer le code vers
viewWillAppear
mais la séquence ne fonctionnera pas si tôt. - Lorsqu'ils se déconnectent, toutes les données se trouvent toujours dans tous les contrôleurs de vue. S'ils se connectent à un nouveau compte, les anciennes données de compte sont toujours affichées jusqu'à ce qu'elles soient actualisées. J'ai besoin d'un moyen d'effacer cela facilement lors de la déconnexion.
Je suis prêt à retravailler cela. J'ai envisagé de faire de l'écran de connexion le contrôleur de vue racine ou de créer un contrôleur de navigation dans l'AppDelegate pour tout gérer ... Je ne suis tout simplement pas sûr de la meilleure méthode à ce stade.
Réponses:
Dans votre appDelegate.m dans votre didFinishLaunchingWithOptions
Dans le fichier SignUpViewController.m
Dans le fichier MyTabThreeViewController.m
Version Swift 4
didFinishLaunchingWithOptions dans le délégué d'application en supposant que votre contrôleur de vue initial est le TabbarController signé.
Dans le contrôleur de vue d'inscription:
MyTabThreeViewController
la source
AppDelegate
intérieurUIViewController
etwindow.rootViewController
y installer. Je ne considère pas cela comme une "meilleure pratique".-1
sans poster de réponse: stackoverflow.com/a/30664935/1226304AppDelegate
intérieurUIViewController
-1 pour le stockage de la clé de connexionNSUserDefaults
. C'est très-très peu sûr pour ce genre de données!Voici ce que j'ai fini par faire pour tout accomplir. La seule chose que vous devez considérer en plus de cela est (a) le processus de connexion et (b) où vous stockez les données de votre application (dans ce cas, j'ai utilisé un singleton).
Comme vous pouvez le voir, le contrôleur de vue racine est mon contrôleur de l'onglet principal . J'ai fait cela car après que l'utilisateur s'est connecté, je veux que l'application se lance directement dans le premier onglet. (Cela évite tout "scintillement" lorsque la vue de connexion s'affiche temporairement.)
AppDelegate.m
Dans ce fichier, je vérifie si l'utilisateur est déjà connecté. Sinon, je pousse le contrôleur d'affichage de connexion. Je gère également le processus de déconnexion, où j'efface les données et affiche la vue de connexion.
LoginViewController.m
Ici, si la connexion réussit, je rejette simplement la vue et envoie une notification.
la source
[self.window makeKeyAndVisible]; [self.window.rootViewController presentViewController:viewController animated:animated completion:nil];
parself.window.rootViewController = viewController;
pour éviter le scintillement. Pour l'animer, il suffit de l'envelopper dans un[UIView transitionWithView...];
EDIT: ajouter une action de déconnexion.
1. Préparez tout d'abord le dossier du délégué de l'application
AppDelegate.h
AppDelegate.m
2. Créez une classe nommée User.
User.h
User.m
3. Créez un nouveau contrôleur RootViewController et connecté avec la première vue, où se trouve le bouton de connexion. Ajoutez également un ID de storyboard: "initialView".
RootViewController.h
RootViewController.m
4. Créez un nouveau contrôleur LoginViewController et connecté avec la vue de connexion.
LoginViewController.h
LoginViewController.m
5. À la fin, ajoutez un nouveau contrôleur ProfileViewController et connecté à la vue de profil dans l'onglet ViewViewController.
ProfileViewController.h
ProfileViewController.m
LoginExample est un exemple de projet pour une aide supplémentaire.
la source
Je n'ai pas aimé la réponse de bhavya à cause de l'utilisation de l'
AppDelegate
intérieur des contrôleurs de vue et le réglagerootViewController
n'a pas d'animation. Et la réponse de Trevor a un problème avec le contrôleur de vue clignotant sur iOS8.UPD 18/07/2015
AppDelegate dans les contrôleurs de vue:
La modification de l'état (propriétés) d'AppDelegate à l'intérieur du contrôleur de vue interrompt l'encapsulation.
Hiérarchie très simple des objets dans chaque projet iOS:
AppDelegate (possède
window
etrootViewController
)ViewController (propriétaire
view
)Il est normal que les objets du haut changent les objets du bas, car ils les créent. Mais ce n'est pas correct si des objets en bas changent des objets au-dessus d'eux (j'ai décrit un principe de programmation / POO de base: DIP (Dependency Inversion Principle: le module de haut niveau ne doit pas dépendre du module de bas niveau, mais ils doivent dépendre des abstractions) ).
Si un objet change un objet de cette hiérarchie, tôt ou tard, il y aura un gâchis dans le code. Cela pourrait être correct sur les petits projets, mais ce n'est pas amusant de creuser ce gâchis sur les projets de bits =]
UPD 18/07/2015
Je réplique les animations du contrôleur modal en utilisant
UINavigationController
(tl; dr: vérifiez le projet ).j'utilise
UINavigationController
pour présenter tous les contrôleurs de mon application. Initialement, j'ai affiché le contrôleur de vue de connexion dans la pile de navigation avec une animation push / pop simple. J'ai alors décidé de le changer en modal avec un minimum de changements.Comment ça fonctionne:
Le contrôleur de vue initial (ou
self.window.rootViewController
) est UINavigationController avec ProgressViewController en tant querootViewController
. Je montre ProgressViewController parce que DataModel peut prendre un certain temps pour s'initialiser car il contient sa pile de données de base comme dans cet article (j'aime vraiment cette approche).AppDelegate est responsable de l'obtention des mises à jour du statut de connexion.
DataModel gère la connexion / déconnexion des utilisateurs et AppDelegate observe sa
userLoggedIn
propriété via KVO. Sans doute pas la meilleure méthode pour le faire, mais cela fonctionne pour moi. (Pourquoi KVO est mauvais, vous pouvez vérifier dans tel ou tel article (Pourquoi ne pas utiliser les notifications?).ModalDismissAnimator et ModalPresentAnimator sont utilisés pour personnaliser l'animation push par défaut.
Comment fonctionne la logique des animateurs:
AppDelegate se définit comme un délégué de
self.window.rootViewController
(qui est UINavigationController).AppDelegate renvoie l'un des animateurs
-[AppDelegate navigationController:animationControllerForOperation:fromViewController:toViewController:]
si nécessaire.Les animateurs mettent en œuvre
-transitionDuration:
et-animateTransition:
méthodes.-[ModalPresentAnimator animateTransition:]
:Le projet de test est ici .
la source
AppDelegate
(je serais intéressé de comprendre pourquoi vous le faites) - mais votre commentaire sur le manque d'animation est très valable. Cela peut être résolu par cette réponse: stackoverflow.com/questions/8053832/…UITabBarController
depuis très longtemps. Je commencerais probablement par l' approche de la fenêtre au lieu de manipuler les contrôleurs de vue.Voici ma solution Swifty pour tous les futurs spectateurs.
1) Créez un protocole pour gérer les fonctions de connexion et de déconnexion:
2) Étendez ledit protocole et fournissez ici la fonctionnalité de déconnexion:
3) Ensuite, je peux conformer mon AppDelegate au protocole LoginFlowHandler et appeler
handleLogin
au démarrage:À partir de là, mon extension de protocole gérera la logique ou déterminera si l'utilisateur est connecté / déconnecté, puis modifie le rootViewController de Windows en conséquence!
la source
LoginFlowHandler
. Suis-je en train de manquer quelque chose? En outre, je suppose que ce code gère uniquement la connexion au démarrage. Comment gérer la déconnexion d'un contrôleur de vue?AppState
implémentation dépendrait donc de la façon dont vous enregistrez vos données utilisateur sur le disque.handleLogout
fonctionnalité?LoginFlowHandler
protocole. Ensuite, vous obtiendrez la portée pour pouvoir appeler la méthode handleLogout. Voir mon étape 3 pour un exemple de la façon dont j'ai fait cela pour la classe AppDelegate.Faire cela à partir du délégué de l'application n'est PAS recommandé. AppDelegate gère le cycle de vie de l'application lié au lancement, à la suspension, à l'arrêt, etc. Je suggère de le faire à partir de votre contrôleur de vue initial dans le
viewDidAppear
. Vous pouvezself.presentViewController
etself.dismissViewController
depuis le contrôleur de vue de connexion. Enregistrez unebool
cléNSUserDefaults
pour voir si elle est lancée pour la première fois.la source
Après avoir créé LoginViewController et TabBarController , nous devons ajouter un StoryboardID comme « loginViewController » et « tabBarController » respectivement.
Ensuite, je préfère créer la structure Constant :
Dans LoginViewController, ajoutez IBAction :
Dans ProfileViewController, ajoutez IBAction :
Dans AppDelegate, ajoutez une ligne de code dans didFinishLaunchingWithOptions :
Enfin créer classe Switcher :
C'est tout!
la source
Dans Xcode 7, vous pouvez avoir plusieurs StoryBoards. Il sera préférable de conserver le flux de connexion dans un storyboard séparé.
Cela peut être fait en utilisant SELECT VIEWCONTROLLER> Editor> Refactor to Storyboard
Et voici la version Swift pour définir une vue comme RootViewContoller-
la source
J'utilise ceci pour vérifier le premier lancement:
(si l'utilisateur supprime l'application et la réinstalle, cela compte comme un premier lancement)
Dans l'AppDelegate, je vérifie le premier lancement et crée un contrôleur de navigation avec les écrans de connexion (connexion et enregistrement), que je mets en haut de la fenêtre principale actuelle:
Comme il se trouve au-dessus du contrôleur de vue normal, il est indépendant du reste de votre application et vous pouvez simplement fermer le contrôleur de vue si vous n'en avez plus besoin. Et vous pouvez également présenter la vue de cette façon, si l'utilisateur appuie manuellement sur un bouton.
BTW: J'enregistre les données de connexion de mes utilisateurs comme ceci:
Pour la déconnexion: je me suis éloigné de CoreData (trop lent) et j'utilise NSArrays et NSDictionaries pour gérer mes données maintenant. La déconnexion signifie simplement de vider ces tableaux et dictionnaires. De plus, je m'assure de définir mes données dans viewWillAppear.
C'est tout.
la source
Je suis dans la même situation que vous et la solution que j'ai trouvée pour nettoyer les données supprime tous les trucs CoreData sur lesquels mes contrôleurs de vue s'appuient pour dessiner leurs informations. Mais j'ai toujours trouvé cette approche très mauvaise, je pense qu'une façon plus élégante de le faire peut être accomplie sans story-boards et en utilisant uniquement du code pour gérer les transitions entre les contrôleurs de vue.
J'ai trouvé ce projet chez Github qui ne fait tout cela que par code et il est assez facile à comprendre. Ils utilisent un menu latéral de type Facebook et ce qu'ils font, c'est changer le contrôleur de vue centrale selon que l'utilisateur est connecté ou non. Lorsque l'utilisateur se déconnecte, le
appDelegate
supprime les données de CoreData et redéfinit le contrôleur de vue principal sur l'écran de connexion.la source
J'ai eu un problème similaire à résoudre dans une application et j'ai utilisé la méthode suivante. Je n'ai pas utilisé de notifications pour gérer la navigation.
J'ai trois storyboards dans l'application.
Mon storyboard initial dans l'application est le storyboard de l'écran Splash. J'ai le contrôleur de navigation comme racine de la table de connexion et de la barre d'onglets pour gérer les navigations du contrôleur de vue.
J'ai créé une classe Navigator pour gérer la navigation de l'application et cela ressemble à ceci:
Examinons les scénarios possibles:
Puisque j'ai le contrôleur de navigation comme racine, j'instancie le contrôleur de navigation comme contrôleur de vue initial.
Cela supprime le storyboard slpash de la racine de la fenêtre de l'application et le remplace par le storyboard de connexion.
À partir du storyboard de connexion, lorsque l'utilisateur est correctement connecté, j'enregistre les données utilisateur dans les valeurs par défaut de l'utilisateur et initialise un singleton UserData pour accéder aux détails de l'utilisateur. Le storyboard de la barre d'onglets est ensuite chargé à l'aide de la méthode du navigateur.
Maintenant, l'utilisateur se déconnecte de l'écran des paramètres dans la barre d'onglets. J'efface toutes les données utilisateur enregistrées et accède à l'écran de connexion.
Lorsque l'utilisateur lance l'application, l'écran Splash est chargé. Je vérifie si l'utilisateur est connecté et accède aux données utilisateur à partir des valeurs par défaut de l'utilisateur. Ensuite, initialisez le singleton UserData et affiche la barre d'onglets au lieu de l'écran de connexion.
la source
Merci à la solution de bhavya. Il y a eu deux réponses sur swift, mais celles-ci ne sont pas très intactes. Je l'ai fait dans le swift3.Below est le code principal.
Dans AppDelegate.swift
Dans SignUpViewController.swift
Dans la fonction logOutAction
la source
entrez la description de l'image ici
In App Delegate.m
}
view controller.m In view did load
}
Action du bouton de déconnexion
la source
NSUserDefaults
est très peu sécurisée pour ce type de données!