Log In and UI Reset
Instagram Firebase
In this lesson, we fix up the remaining components of our LoginController to allow the user the ability to log back into the application. In addition to this, we'll inspect the behavior of our application after we've dismiss the login and registration screens. To fix the issues that arise from logging in our users, we'll implement a quick fix that will reset the UI for our MainTabBarController.

Comments (52)
jacquesj
6 years ago
Hello Brian, I was just curious on a conceptual level are we just throwing the old views (with their data) off the heap each time we do the set up again? Does the dismiss function also toss the current view off the heap? Thank you!
Brian Voong
6 years ago
TTTTgg
6 years ago
Hi Brain, If i also want to add a check that alerts user they did not choose a profile picture, what to do? Thanks
Brian Voong
6 years ago
njkumar303@gmail.com
6 years ago
Hey Brian, After successfuly logging in, the login page dismisses, however it goes back to the previous page (in my case a page that has the option to either login or sign up) as opposed to the MainTabBarController. Any idea why this is happening?
Brian Voong
6 years ago
Obrac
5 years ago
Hi Brian, I am using both the Audible tutorial and this one for my IOs dev. project. Oddly, i've come to the same problem as the previous user. I've completely removed Storyboards and yet I still can't get the dismiss to work properly. The user has to log in at least once before successive logins can work as in the course(guard let mainTabBar returns nil on the first try?). First-time logins are dismissed back to signup/login VC. Any thoughts?
Brian Voong
5 years ago
Obrac
5 years ago
Hey Brian, Forgive me, Brian, however, the version of the project already includes push notifications and I'm yet to register with APPLE Devs license. From my past experiences, `prior to the recent download of the course source code, the app was working fine from source code. Frankly, man, I can't even begin to think straight on which line could be causing this, if it's only one line... AppDelegate is only calling: (in regards to this) window = UIWIndow() window?.makeKeyandVisible() window?.rootViewController = mainTabBarController() login Method in the loginVC is pretty much the same, except for the Strings, Firebase auth syntax(using swift 3.2 - if that makes a difference) and thats it...
Brian Voong
5 years ago
Obrac
5 years ago
Hey Brian, It does, however, what sweeps me off is the fact that it only happens on first time users..ie. if the user is signing up/login in for the first time the app dismisses to the signup/login vc, otherwise, when the user signs up/logs in a second time, they are taken to the settings page, where the logout button resides, as their "welcome" screen, completely bypassing the actual welcome screen which is tabBar's 0 index.
Aleix Díaz
6 years ago
Hi Brian, Why can't we use: MainTabBarController ( ). setupViewsControllers insead of calling UIAppliaction ? I tried and the userview doesn't refresh but I don't know why.
Brian Voong
6 years ago
TTTTgg
6 years ago
Hi Brian, Do you know what frame or api i can use, if i want to achieve the functionality that send a link through email to users so that they can click and go back to app to reset their password. Or the one which did the similar thing to reset the password.
Игорь Магурян
6 years ago
You need to take a look at URLScheme inside of Info.plist, over there you can set url to your app. Which will be looked like something like that ... "yourAppName://?anyParameterYouWantToSend=value"
Игорь Магурян
6 years ago
Hi, I'm very suprised, that we don't need to use lazy vars to access self in closure block, anymore..?!
Clive Wong Toh Soon
6 years ago
I want to make the profileImage to profileImage : UIButton instead and execute the upload image function as taught in the SignUpPageViewController. However, present() is only available in UIViewCell or UICollectionViewController. How do I make present() executable in UICollectionViewCell for the UserProfileHeaderViewCell?
Brian Voong
6 years ago
smiller193
6 years ago
Is anyone having an issue with the input accessory view getting stuck at the bottom? When exiting comment screen
jalong4
6 years ago
when you call mainTabBarController.setupViewControllers() from LoginController and SignUpController why does it work without being forced onto the main thread since setupViewControllers() does UI stuff? Is it because you haven't dismissed the current controller in both cases? Thanks, love the course.
Brian Voong
6 years ago
jalong4
6 years ago
I see. Thanks for explaining.
darrellbulloch
6 years ago
I noticed that when dismissing the LoginController, the app return to a black screen. It seems that this is because the MainTabBarController did not get its viewControllers property set prior to presenting the LoginController. Is that correct? If so, why doesn't you app behave the same?
Brian Voong
6 years ago
darrellbulloch
6 years ago
I needed to call setupViewControllers() in the MainTabBarController when dismissing the LoginController
darrellbulloch
6 years ago
Thanks Brian - I didn't notice your reply before I replied :-}
jalong4
6 years ago
I noticed that the SignUpController doesn't format correctly in landscape on some phones. There isn't room for all the buttons. What would you normally do this in case? One idea was to not show the plusPhoto in landscape (the user would have to go to portrait if they wanted to set the photo in this case). Another idea was leave in the plusPhoto but to put the stackView of the buttons into a scrollView and allow it to scroll. I realize users probably wouldn't want to sign up in landscape anyway but probably a good practice to handle this rather than leaving what looks like broken UI. Another question is what is a good UX for showing the rules for things like weak passwords and invalid email addresses, etc. In my implementation I've implemented regEx expressions for all three fields and use them from both LoginController and SignUpController (like isEmailValid, isPasswordValid and isUsernameValid). My isFormValid just returns an && of all 3 of these. I suppose I could have an info button to explain the validation rules or pop up a model. Just wondering your thoughts for a good UX design for this. Thanks much. Love the course.
Brian Voong
6 years ago
jalong4
6 years ago
Is it easy to disable landscape only for certain view controllers? I can see cases where you might want to allow landscape for other viewcontrollers but not login/registration.
Brian Voong
6 years ago
Mauricio Figueroa Olivares
5 years ago
How can the components be reused, for example, the stack view with the text fields and the button without repeating the code?
Brian Voong
5 years ago
Mauricio Figueroa Olivares
5 years ago
Thanks Bryan.
dsalzr
5 years ago
Would it be possible to store the User somewhere centrally? Since all views/components will potentially need access to the current user. When the current user changes, all underlying views/components have access to the updated data in User. (I'm coming at it from a web development perspective so I'm not sure if it works the same way in iOS)
Brian Voong
5 years ago
dsalzr
5 years ago
Nice. Thanks Brian.
AlfieLBTA
5 years ago
Saving it to UserDefaults counts as a singleton ? and is it a good approach?
Tokyojogo
5 years ago
Hi Brian, When checking if there is an existing user, right now its in the maintabbarcontroller so when we launch the app, I can see the userprofilecontroller gets loaded first then the loginController is presented (when the user is logged out). Wouldn't it be better to put this inside appdelegate and use an if statement to know which one to display? If its done like this, will there be any changed needed in the code for login/signup (presenting the VC part)? Thanks.
Brian Voong
5 years ago
Ouen_theara
5 years ago
Hello sir , I want to customize dialog pop up style with adding any controls can u show me please
Brian Voong
5 years ago
Sanket Ray
5 years ago
To access "setupViewControllers" func of "mainTabBarController", you wrote : guard let mainTabBarController = UIApplication.shared.keyWindow?.rootViewController as? MainTabBarController else { return } cant we simply change " func setupViewControllers" to " static func setupViewControllers" ? Wouldn't it be easier?
Brian Voong
5 years ago
Rakesh Kumar
5 years ago
Hello Brianvoong, Great tutorial. Instead of print statement in login and signUp controllers can you please show proper way of error handling. other thing is showing activity indicator in login and signup process. Thanks.
frempong
5 years ago
Hi Brian, quick question; min 11.42: Can't we just store a reference to collectionView in userProfileViewController in loginViewController and just call collectionView.reloadData() when dismissing the loginViewController?
Brian Voong
5 years ago
corbinyo
5 years ago
Great Lesson - Learning so much
franchise099
5 years ago
Brian, when I make my millions I will be sure to break you off a piece!
Brian Voong
5 years ago
Amit
5 years ago
Hey Brian, How to match/change the color of the top notch area with the first view. The notch area always takes the default view color. e.g.If we have a video player, just below the notch area (following safeAreaLayoutGuid), how to make the notch area black in color. Please, help me out here.
miguelsrochajr@gmail.com
5 years ago
Hi, Brian! I am trying to set a UserDefaults variable after dismissing the LoginController. It saves and I can access it when I get back to MainTabBarController. However, when I close the app and come back again, the user default no longe exists. Do you know there is any problem with the threads when setting a user default value in the completion handler?
AlfieLBTA
5 years ago
Hello Brian: Do you know how to get the Fire base error code back, so i can test against it, and show a custom error message accordingly. if i print the error i get this : Error Domain=FIRAuthErrorDomain Code=17009 "The password is invalid or the user does not have a password." UserInfo={NSLocalizedDescription=The password is invalid or the user does not have a password., error_name=ERROR_WRONG_PASSWORD}
tsangaris
5 years ago
I was about to ask why don't we just "present" the appropriate view controller when logging in / logging out but then I found this Reddit post: https://www.reddit.com/r/swift/comments/817mgv/dismiss_vs_present_view_controller/ But I have a slightly different app structure than the InstagramFirebase app: When a user is not logged in (check performed in MainTabBarController), I want to display a landing page where you will see the first half part of the View to be a collectionView scrolling horizontally and the other half part to contain 2 buttons: 1 for registration and 1 for login. This way we will have the MainTabBarController as rootViewController, then (if the user is not logged in), we will go to LandingPageController, then we will click on Login button and go to LoginController. The questions is: How do I dismiss both LoginController and LandingPageController before moving to MainTabBarController as a logged in user? Cheers!
Brian Voong
5 years ago
tsangaris
5 years ago
Hi Brian, To simplify this, what if instead of LoginController, RegisterController, and MainTabBarController, you had an additional LandingController, where the user would land if not logged in (kinda like Spotify app for iOS)? Would you follow the same procedure? In my case, instead of dismissing the appropriate view controller I choose to present the MainTabBarController in both LoginController and RegisterController. Is this approach wrong? Will it affect the app in terms of memory? Thanks in advance.
tsangaris
5 years ago
** Also by presenting the MainTabBarController I don't need to go through the procedure of: guard let mainTabBarController = UIApplication.shared.keyWindow?.rootViewController as? MainTabBarController else { return } mainTabBarController.setupViewControllers() But i dont think that there is no caveat in just presenting the MainTabBarController and call it a day.
p31d3ng
5 years ago
Hi Brian, To be honest I'd say there is a huge design flaw here. Every time a user log out and log back in (or sign up), a new UserProfileController with NavController will spawn. I've checked the mem address of each NavControllers - they are all different. We should either reuse the original ones or destroy them to prevent memory leaks since they're not accessible any longer. To my understanding, get things done correctly is the most important thing to an engineer. And I really don't think you'll make such a mistake in your daily job since you're a lead engineer. There's no way such code can pass code review. I hope there will be an updated version of the code which would have a correct design with controller flow.
p31d3ng
5 years ago
Ops, sorry I just read the first post of the thread. You mentioned that if there's no retain cycle it should be automatically cleaned up. I just check again. Yes, you're right. The UserProfileController will actually get destroyed automatically... I put some print statement in deinit and saw the original ones are cleaned up automatically. I'm sorry for putting the comments without careful consideration!
edison1
5 years ago
How can we update the user profile picture once we're in the app?
tsangaris
5 years ago
Hi guys, I had a problem where the LoginController would not deallocate when dismissed. My app structure is somewhat different (i like the iOS Spotify app structure better). The only difference, is that, i like to separate view elements from the view controller (Brian taught me that also!). Doing that created a retain cycle that would not allow LoginController to be deallocated. You can find more about this to my StackOverflow question (and answer) here: https://stackoverflow.com/questions/51051838/swift-presenting-modally-and-dismissing-a-navigation-controller/51078752#51078752 Now i feel ready to move forward to the next lesson! :) Damn OCD!!!
OfftheCode
5 years ago
Thanks for great explanation on stack, and guiding people through your journey of finding solution!
eliamyro
5 years ago
Hi guys! Instead of using the UIApplication.shared.keyWindow?.rootViewController as? MainTabBarController I notify the MainTabBarController setupViewControllers() using NSNotificationCenter. It seems that everything works as intended but which approach is better?
Mahmoud Hany
5 years ago
Hi, Brian is it right to check if user logged in from appDelegate.swift ?? Thanks for your awesome videos BTW.
srithan
5 years ago
I am half way through this episode. I am able to display user id as navigation item title. But The profile photo and the username are not showing up. I printed those values in setupProfileImage(). It is showing <<null>>
roygbiv
4 years ago
Hi Brian, I have a problem upon logging in. The error message is "libc++abi.dylib: terminating with uncaught exception of type NSException"; Thread 2: signal SIGABRT I've tried cleaning my code but to no avail. Kindly advise thanks
roygbiv
4 years ago
Hi Brian, I've resolved it. Apparantly Auth.auth() has 2 different auto complete: 1. Auth.auth().signIn(withEmail: <String>, password: <String>) { (user, err) in code } VS 2. Auth.auth().signIn(withEmail: email, link: password) { (user, err) in code } The difference is in the 2nd argument.
frankcrest
4 years ago
good one
yuiso
4 years ago
Hi Brian, I have a question: Why we don't have to encrypt username and password before we send it to Firebase? Please help, thanks:)
Brian Voong
4 years ago
flashtrend
4 years ago
Hi Brian, can we sign in using username rather than using email? Thanks!
Brian Voong
4 years ago
Pao
4 years ago
Hi Brian, instead of using dismiss() once the user successfully logged in, can we use present() to present the viewController and avoid the use of UIApplication.shared.keywindow.rootViewController ? I'm asking because I can't figure out how to implement your technique with my app where my RootVC is a UICollectionView embeded in a navigationController. And using present() seems to work fine. Thank you very much
tsangaris
4 years ago
@Pao, I believe that by using dismiss() you help with the memory leaks. If you use present() you add more VCs and eventually, you need more memory for this: https://tech.showmax.com/2019/02/uiviewcontroller-memory-leak/
anantangad
4 years ago
Hey Brian, I remember you discussed how to remove unnecessary statements from the console, but I don't know in which video. Could you please refer me. Would be big help. Thanks.
Daniel Peach
4 years ago
Hey if you haven't found this answer yet, go to Product > Scheme > Edit Scheme > Run > Arguments > Environment Variables, and add OS_ACTIVITY_MODE: disable
rgarcia
4 years ago
Hi Brian, is possible to include a video on the section of the Login with FaceID please. Thanks for an amazing training
Bùi Xuân Huy
4 years ago
Hey Brian, at 9:30, why was the black screen showed up?
frankcrest
4 years ago
how do i solve this error...libc++abi.dylib: terminating with uncaught exception of type NSException (lldb) ? I have the exact same code..
frankcrest
4 years ago
Looks like the order of the coding is very specific in terms of logging out, coding, login, if you miss one step/ do it in the wrong order the code will get stuck somewhere..i had to restart from beginning of lesson to solve this
malrhex
4 years ago
Really good stuff.
malrhex
4 years ago
I just post this and it says 2 weeks ago xD
Lavyox DWz
4 years ago
Hi Brian, I have a problem here with adding photo to a new user in here .. when a photo is taken from the device the frame is not a circle anymore .. though i didn't change the code .. plusePhotoButton.layer.cornerRadius = plusePhotoButton.frame.width / 2 plusePhotoButton.layer.masksToBounds = true I think it's because we changed the anchor but I don't know how to fix it
Brian Voong
4 years ago
Lavyox DWz
4 years ago
it didn't work
Lavyox DWz
4 years ago
I found a way .. using paddings left and right .. but I'm not sure about the math XD .. it looks perfect xD let number:CGFloat = view.frame.width/3.205128205 // = 117 for iphone 8 for both paddings left and right thanks brain for your time and help :D
christiaan2211
4 years ago
Hi Brain, I am currently using the fetchUser() function for every time I need to get user data like first name, last name, and other information stored in the database. I want to set a global variable containing the user's database information so that I can easily fill in the UILabels with the correct value. (like first name etc). I cannot find a way to save the information as global...
christiaan2211
4 years ago
I did manage a way to save the user data as UserDefaults but cannot figure out how to update the labels connected to this userdefaults data once I change the user defaults, this requires a restart of the app but needs to be instant. There Must be a way for this, could you help me out?
Max Budnik
4 years ago
Hi, all! If you have some problem with MainTabbarController when he disappears, after first login in app, the next code will help you fix that bug. override func viewWillAppear(_ animated: Bool) { super.viewDidAppear(animated) if Auth.auth().currentUser == nil { //show if not logged in DispatchQueue.main.async { let loginController = LoginController() let navController = UINavigationController(rootViewController: loginController) self.present(navController, animated: true, completion: nil) } return } setupViewControllers() } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) if let vcs = viewControllers { for (_,vc) in vcs.enumerated() { vc.view.removeFromSuperview() } } } I hope that help.
Max Budnik
4 years ago
Oh, sorry. Please fix that code in viewWillApear() override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) //- > not super.viewDidAppear(animated)
Max Budnik
4 years ago
Brain, when we created our UserProfileController in mainTabBarController.setupViewControllers() in function handleLogin, Are we creating memory leaks? I can call deinit in UserProfileController but he never calling. Could you help me to undestand this.
Max Budnik
4 years ago
Sory. Brian, of course.
Brian Voong
4 years ago
kevinblee
3 years ago
Hi brian, how do i fix this, it says that keyWindow was deprecated in iOS 13.0. Help
Brian Voong
3 years ago
kevinblee
3 years ago
thank you Brian!
juan4
3 years ago
How do I access mainTabBarController.setupViewControllers() with let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
juan4
3 years ago
I tried let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first as? MainTabBarController window?.setupViewControllers() but the user profile does not update.
juan4
3 years ago
Lol Never mind just figured it out ;) forgot to add rootViewController smh. let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController as? MainTabBarController window?.setupViewControllers() I noticed the user profile loads faster this way though. let window = UIApplication.shared.connectedScenes .filter({$0.activationState == .foregroundActive}) .map({$0 as? UIWindowScene}) .compactMap({$0}) .first?.windows .filter({$0.isKeyWindow}).first?.rootViewController as? MainTabBarController window?.setupViewControllers()
tsangaris
3 years ago
Looks like that now you use SceneDelegate to set the rootViewController. guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(frame: windowScene.coordinateSpace.bounds) window?.windowScene = windowScene window?.rootViewController = MainTabBarVC() window?.makeKeyAndVisible()
rolvee
3 years ago
You saved me a huge headache lol
vincentasantos
3 years ago
When I log in as an existing user, the username and profile picture does not show up in the header, but shows the long unique identifier. But when I sign up as a new user, the username and picture comes up. How can I get the username and profile picture to show up when I log in as an existing user?
esong2288
3 years ago
For iPhoneXs+ is there a way to have the logoView anchor to the safeAreaLayouts and set the background color of the notch area to the blue color?
tsangaris
3 years ago
If you want to read more about retain cycles and delegate pattern then this article is a great resource: https://medium.com/anysuggestion/preventing-memory-leaks-with-swift-compile-time-safety-49b845df4dc6
dannyp75
3 years ago
I am trying to build this project and it fails, one of the first issues is Swift 5 conversion. It can't convert due to syntax errors.
dannyp75
3 years ago
Brian, For the KeyWindow issue do you replace: guard let mainTabBarController = UIApplication.shared.keyWindow?.rootViewController as? MainTabBarController else { return } with let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
dannyp75
3 years ago
I got passed the KeyWindow error but the project still does not run. I run it and the screen goes white, then black.
bvv
2 years ago
Hi Brain, When I add : guard let mainTabBarController = UIApplication.shared.keyWindow?.rootViewController as? UITabBarController else { return } mainTabBarController.setupViewControllers() it shows an error that 'keyWindow' was deprecated in iOS 13.0: Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes. This is not work for me, and I still have the problem of login with a new user but show the previous user information. Can u please tell me what wrong with it? Thanks!
bvv
2 years ago
I saw the let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first and it doesn't work for me. May face the same problem as I do with the xcode12?
HELP & SUPPORT