Logging Out with UIAlertController
Instagram Firebase
To further complete our profile page, we'll implement the feature that allows the user to log out and log back in. Let's use the UIAlertController Action Sheet component to present the necessary options to our user. Once we execute a proper sign out, I'll demonstrate a technique that prompts the user to log back in right away when the app starts.

Comments (29)
lbta
6 years ago
lbta
6 years ago
Mustafa Sahin
6 years ago
We are waiting :)) And do you think to add post time ago??
Fred van Rijswijk
6 years ago
great!! Love this course, completely switching from full storyboards iOS app to completely pure code ;-)
tomxue
6 years ago
Did you release today??
Brian Voong
6 years ago
Brian Voong
6 years ago
Mustafa Sahin
6 years ago
I want to buy this course but wait it all done. Can I download source code for swift 3?
Tashinyima
6 years ago
Hi Brian, After updating to Xcode 8.3 / Swift 3.1 public release I am not able to get update from firebase and display the profileimage and username on the UI. I search online about the warning and it advice us to ignore the waring for timebeing but not able to find any info to display image and username. Please help...
Brian Voong
6 years ago
Tashinyima
6 years ago
Hi Brian, I am not getting any specific message in the console. I tried to debug it and I am getting nil value for profileImageUrl and username. Since Xcode 8.3 is bit buggy I reverted back to Xcode 8.2.1. Now it's working as before... Thanks for prompt response :)
rebeloper
6 years ago
Instagram is iPhone only. If someone might want to use the UIAlertController as an actionSheet on an iPad be aware that you will need to add: alertController.popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem The code would look something like: func handleLogOut() { let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) // added for iPad alertController.popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem alertController.addAction(UIAlertAction(title: "Log Out", style: .destructive, handler: { (_) in do { try FIRAuth.auth()?.signOut() //what happens? we need to present some kind of login controller } catch let signOutErr { print("Failed to sign out:", signOutErr) } })) alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) present(alertController, animated: true, completion: nil) } Source: http://stackoverflow.com/questions/28089898/actionsheet-not-working-ipad
Dan Boyle
6 years ago
Hey Brian... do you have any good articles or resources to learn more about when you're on a background thread? I'll search around but just wanted to see if you had some go to resources. Thanks.
Brian Voong
6 years ago
Kamau Exom
6 years ago
How do you add a gradient to the background?
Brian Voong
6 years ago
Kamau Exom
6 years ago
Thanks... these videos are awesome. I'm glad that I paid for the Instagram course.
saicharan123
6 years ago
Can we use Present instead of pushview in the handleShowSignup ? i meant some thing like this. func handleSinup () { let signupController = SignupController() DispatchQueue.main.async { self.present(signupController, animated: true, completion: nil) } } any drawbacks of using present instead of pushview method you've shown ?
Adam El-Kadi
5 years ago
Not really
smiller193
6 years ago
Is anyone having an issue with the input accessory view getting stuck at the bottom? When exiting comment screen
Ally Makongo
6 years ago
I am using TabBarViewContoller to hold my view controllers (using storyboards). Which place is better and not error prone to check if user has log in or not from firebase?
Brian Voong
5 years ago
Adam El-Kadi
5 years ago
Brain I think I know what the issue was when it turned black was that the program tried to enter the profile view controller and the sign up controller at the same time so it kind of mixed then together.
Tokyojogo
5 years ago
Hi Brian, So I'm doing the bottom text at the login and I wanted to separate the button and the text. I have the following code based on what I've learned from the signup page but I can't seem to center it. let signUpButton: UIButton = { let button = UIButton() button.setTitle("Sign up", for: .normal) button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 12) button.setTitleColor(.blue, for: .normal) return button }() let signUpLabel: UILabel = { let label = UILabel() label.text = "Don't have an account? " label.font = UIFont.boldSystemFont(ofSize: 12) label.textColor = UIColor.lightGray label.textAlignment = .right return label }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white setupSignUpView() } fileprivate func setupSignUpView() { let stackView = UIStackView(arrangedSubviews: [signUpLabel, signUpButton]) stackView.axis = .horizontal stackView.center = view.center stackView.distribution = .fillProportionally view.addSubview(stackView) stackView.anchor(top: nil, left: view.leadingAnchor, bottom: view.bottomAnchor, right: view.trailingAnchor, paddingTop: 0, paddingLeft: 100, paddingBottom: 0, paddingRight: 100, width: 0, height: 50) //stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true } so even when I tried the centerXAnchor constraint, its not centering properly. I used left and right padding = 100 other wise its displaying on the right most side (bec the label alignment is to the right and I can't figure out how to align the button text to the left).
Tokyojogo
5 years ago
Also, when clicking on the button here, its acting like a button but visually, its not doing anything like how you would expect a button to react
Brian Voong
5 years ago
Tokyojogo
5 years ago
Thank you for the reply Brian. So I should place them in a view and not in a stackView? I'll check out the attributedText and try to apply it.
Brian Voong
5 years ago
Tokyojogo
5 years ago
Hi Brian, I hacked it with this (for anyone interested)... let signUpButton: UIButton = { let button = UIButton() button.setTitle(" Sign up here.", for: .normal) button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 12) button.setTitleColor(.blue, for: .normal) button.addTarget(self, action: #selector(handleShowSingUp), for: .touchUpInside) return button }() let signUpLabel: UILabel = { let label = UILabel() label.text = "Don't have an account?" label.font = UIFont.boldSystemFont(ofSize: 12) label.textColor = UIColor.lightGray label.textAlignment = .right return label }() let signUpView: UIView = { let v = UIView() return v }() override func viewDidLoad() { super.viewDidLoad() navigationController?.isNavigationBarHidden = true view.backgroundColor = .white setupSignUpView() } @objc func handleShowSingUp() { let signUpVC = SignUpVC() navigationController?.pushViewController(signUpVC, animated: true) } fileprivate func setupSignUpView() { view.addSubview(signUpView) signUpView.anchor(top: nil, left: nil, bottom: view.bottomAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 230, height: 50) signUpView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true signUpView.addSubview(signUpLabel) signUpLabel.anchor(top: signUpView.topAnchor, left: signUpView.leadingAnchor, bottom: nil, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 50) signUpView.addSubview(signUpButton) signUpButton.anchor(top: signUpView.topAnchor, left: signUpLabel.trailingAnchor, bottom: nil, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 50) } but how come the button doesn't show anything visually when you click on it? There's no subtle effect when you click on it.
Brian Voong
5 years ago
PatrickVB
5 years ago
I am wonder Why I am getting this Error? Listener at /users/fAMfg2g55DQWT0SqVgFzx2fGnXl1 failed: permission_denied Failed to observe comments
PatrickVB
5 years ago
Never mind. I queried (printed) userID and it was nil, so it worked correctly.
Kritbovorn Taweeyossak
5 years ago
Time: 12.00 on this video '' if Auth.auth().currentUser == nil { DispatchQueue.main.async { let loginViewController = LoginViewController() self.present(loginViewController, animated: true, completion: nil) } return } '' why when I insert these code and Run my App " libc++abi.dylib: terminating with uncaught exception of type NSException " import UIKit import Firebase class MainTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() //------------------ if Auth.auth().currentUser == nil { DispatchQueue.main.async { let loginViewController = LoginViewController() self.present(loginViewController, animated: true, completion: nil) } return } //-------------------------- let layout = UICollectionViewFlowLayout() let userProfileViewController = UserProfileViewController(collectionViewLayout: layout) let navController = UINavigationController(rootViewController: userProfileViewController) navController.tabBarItem.image = UIImage(named: "profile_unselected") navController.tabBarItem.selectedImage = UIImage(named: "profile_selecter") tabBar.tintColor = .black viewControllers = [navController, UIViewController()] }
Brian Voong
5 years ago
Kritbovorn Taweeyossak
5 years ago
libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)
Kritbovorn Taweeyossak
5 years ago
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The default FIRApp instance must be configured before the default FIRAuthinstance can be initialized. One way to ensure that is to call `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) in the App Delegate's `application:didFinishLaunchingWithOptions:` (`application(_:didFinishLaunchingWithOptions:)` in Swift).
Brian Voong
5 years ago
Brian Voong
5 years ago
Kritbovorn Taweeyossak
5 years ago
In AppDelegate.swift , I have it FirebaseApp.configure import UIKit import Firebase /// @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { window = UIWindow() window?.rootViewController = MainTabBarController() FirebaseApp.configure() //// return true }
Brian Voong
5 years ago
Kritbovorn Taweeyossak
5 years ago
Great , Thank you very much , I will follow your lesson forever Sir. Clever Man, Brianvoong
frempong
5 years ago
Was having the same issue here, thanks!!
ronaldruck@live.com
5 years ago
OMG hart to believe that such a simple detail like where the firebaseapp.configure() command is located can make your app crash, I had this issue as well and just by chaging the position of the command fixed it. thanks Brian.
frempong
5 years ago
What is the difference between creating a function called onCheckUser and putting return at the end of that function(inside the function) and doing the if statement as you did(minute 11.16) with the return at the end?. Because they don't give me the same result.
Drew Pasma
5 years ago
signUpButton.anchor(top: nil, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingRight: 0, paddingBottom: 0, width: 0, height: 50) Believe I am calling the correct function to attach the button to the bottom of the login view but when I run the application the button stays at the top of the view. Any reasons for why this is happening would be greatly appreciated
Drew Pasma
5 years ago
Nevermind. Got it. Great course so far. 1/5 of the way there, how much harder does it get?
Michael Evans
5 years ago
After I logged out the user, when I try to run the app it crashes with the following error msg. Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier cellId - must register a nib or a class for the identifier or connect a prototype cell in a storyboard' Any thoughts?
Michael Evans
5 years ago
Fixed. I had the return call inside the DispatchQueue closure so it executed the code below
rehan1531
5 years ago
Hey Brain , The userProfileController is shown to me whenever the app launches I don't know why, here is the code !!! class MainTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() if Auth.auth().currentUser == nil { DispatchQueue.main.async { self.present(LoginController(), animated: true, completion: nil) } return } let layout = UICollectionViewFlowLayout() let userProfileController = UserProfileController(collectionViewLayout: layout) let navController = UINavigationController(rootViewController: userProfileController) navController.tabBarItem.selectedImage = #imageLiteral(resourceName: "profile_selected") navController.tabBarItem.image = #imageLiteral(resourceName: "profile_unselected") tabBar.tintColor = .black viewControllers = [navController,UIViewController()] } }
omari
5 years ago
Hello Brian. If you run the code you always see the MainTabBarcontroller first before the LoginController opens ( where you check if currentUer == nil) this looks very bad . How to fix this ?
petar7
5 years ago
Use show VC instead of present and it will work
Hoov11
5 years ago
I keep getting a black screen and then it crashes. Does that happen to anyone else?
Brian Voong
5 years ago
tsangaris
5 years ago
@Brian, While you are checking for login state in MainTabBarController, is it OK (or more correct) to check the login state inside AppDelegate? // AppDelegate.swift FirebaseApp.configure() self.window = UIWindow(frame: UIScreen.main.bounds) // check wether the user is logged in or not if Auth.auth().currentUser != nil { // User is logged in. // show TabBar controller page self.window?.rootViewController = UINavigationController(rootViewController: MainTabBarController()) } else { // User is not logged in. // show Landing page let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal self.window?.rootViewController = UINavigationController(rootViewController: LandingViewController(collectionViewLayout: layout)) } self.window?.makeKeyAndVisible() ps: great tutorial as always!
Brian Voong
5 years ago
Talia
5 years ago
Hi Brain: 下面这段代码我几乎是粘贴的,但是还是提示错误, 之前运行的时候没有问题,是因为中间我firebase和cocoapods升级了吗?怎么改正呢? @objc func handleSignUp() { guard let email = emailTextField.text, email.characters.count > 0 else { return } guard let username = usernameTextField.text, username.characters.count > 0 else { return } guard let password = passwordTextField.text, password.characters.count > 0 else { return } Auth.auth().createUser(withEmail: email, password: password, completion: { (user: User?, error: Error?) in //错误提示:Cannot convert value of type '(User?, Error?) -> ()' to expected argument type 'AuthDataResultCallback?' (aka 'Optional<(Optional<AuthDataResult>, Optional<Error>) -> ()>') if let err = error { print("Failed to create user:", err) return } print("Successfully created user:", user?.uid ?? "") guard let image = self.plusPhotoButton.imageView?.image else { return } guard let uploadData = UIImageJPEGRepresentation(image, 0.3) else { return } ...
Brian Voong
5 years ago
Talia
5 years ago
下载了,又粘贴了一下,还是同样的错误提示 @objc func handleSignUp() { guard let email = emailTextField.text, email.characters.count > 0 else { return } guard let username = usernameTextField.text, username.characters.count > 0 else { return } guard let password = passwordTextField.text, password.characters.count > 0 else { return } Auth.auth().createUser(withEmail: email, password: password, completion: { (user: FirebaseAuth.User?, error: Error?) in //错误提示:Cannot convert value of type '(User?, Error?) -> ()' to expected argument type 'AuthDataResultCallback?' (aka 'Optional<(Optional<AuthDataResult>, Optional<Error>) -> ()>') if let err = error { print("Failed to create user:", err) return } print("Successfully created user:", user?.uid ?? "") guard let image = self.plusPhotoButton.imageView?.image else { return } guard let uploadData = UIImageJPEGRepresentation(image, 0.3) else { return } ...
Brian Voong
5 years ago
Brian Voong
5 years ago
Talia
5 years ago
谢谢您,metadata也没有downloadURL()了, guard let profileImageUrl = metadata?.downloadURL()?.absoluteString else { return }
Brian Voong
5 years ago
Talia
5 years ago
对不起,我的基础太差了,我不知道应该怎么改
esong2288
5 years ago
I'm sort of confused with how the views are set up. Are only the login and register view controllers nested within the navigation controller, and the User profile controller nested in the Tab bar controller? Also, what's the difference between pushing and popping view controllers to presenting and dismissing. Are they the same thing except push/pop is only for navigation controllers?
Brian Voong
5 years ago
Mwible
5 years ago
Hey Brian! Pretty new to this and loving the tutorial so far. Quick question... When adding the gear icon, my bar button items seem to be stacking in the middle of the nav bar. Ill set the gear icon to the RightBarButtonItem and it will always just center itself in the middle on top of the username. Do you happen to know why this is happening? Thanks!
Brian Voong
5 years ago
Daniel Peach
4 years ago
Oh my gosh! That explanation of NavigationController just made SO much click in my head!
arturfil@hotmail.com
4 years ago
Hey Brian, For some reason my signUpButton is displaying at the top of the screen and I tripled checked that the code was the same. Is there something that could be causing this behavior? Thank in advance.
Clint Larenz Nurse
4 years ago
Did you ever explain how to keep users signed in? Everytime I close the app I have to login back in.
johnicode101
3 years ago
stackoverflow u should fine the lines of code simple
Clint Larenz Nurse
3 years ago
Thanks, yeah I asked this months ago. A lot has changed, definitely have a better understanding
Eugene
4 years ago
Hi Brian, I've got the extra space at the top of the Login and SingUp controllers (between view and status bar). In debug view hierarchy it shows that they have UIView-Encapsulated-Layout-Top: view.minY == 0 @1000 where should i check to fix it? Thanks!
Eugene
4 years ago
i ran downloaded code for this lesson and got the same issue Hope you will help me with this
Eugene
4 years ago
false alarm, the problem was in the Xcode beta
Mike Zhang
4 years ago
HI Brian. Why does the navigationBar not appear on my login screen and above the registration screen. The file for downloading the course is also not displayed.
Mike Zhang
4 years ago
I know the answer. Thank you.
roodrigolemoss
3 years ago
Hi Mike, i am having the same problem, why is happening that?
JoffreyF
3 years ago
In LoginController.swift, you can type this line of code in viewDidLoad : navigationController?.isNavigationBarHidden = true This will hide nav bar for LoginScreen AND for any view that you push from LoginController's navigation controller
Lai Yit Ming
3 years ago
HI Brain, I have got the same error written below that was reported before in earlier comment (by Kritbovorn Taweeyossak, 2 years ago), that you has resolved. However, I did not get to solve it after updating the code based on what you had recommended (i.e. to call FirebaseApp.configure() before setting up the window. in AppDelegate.swift). The difference between my code and Kritbovorn Taweeyossak's code is that: I am using xcode 11.1, and in lesson #1 you had recommended me to move some window set up code to SceneDelegate.swift instead of doing it in AppDelegate. Error symptom: Time: 12.00 on this video '' if Auth.auth().currentUser == nil { DispatchQueue.main.async { let loginViewController = LoginViewController() self.present(loginViewController, animated: true, completion: nil) } return } '' why when I insert these code and Run my App " libc++abi.dylib: terminating with uncaught exception of type NSException "
Lai Yit Ming
3 years ago
I got the answer. Is my mistake. Thank you.
Carlos Henrique
3 years ago
Hi Brain, I 'd like to know if this is the best implementations practice: // In MainTabBarController if Auth.auth().currentUser == nil { DispatchQueue.main.async { let loginController = LoginController() let navController = UINavigationController(rootViewController: loginController) navController.modalPresentationStyle = .fullScreen //this because iOS 13, It's okay this way? self.present(navController, animated: true, completion: nil) } return }
HELP & SUPPORT