Main Tab UI and Fetch User
Instagram Firebase
Now that we've taken care of the important aspects of persistence using Firebase Authentication, Database, and Storage, we can look at building out our main UI. To start off, we'll look at how the Instagram user interface is designed. Then we'll start the process by including our own custom UITabBarController subclass. Once we have the main UI set up, let's also fetch the user's username and display it at the top of our UINavigationBar.

Xcode 11.3+ SceneDelegate Update 4/20/2020

As most of you are probably aware by now, starting with Xcode 11.3, Single View Application projects are now created with a SceneDelegate file. This file is used to manange the scenes in your application and thus also contains the entry point of your app. Because of this change, we'll need to go about setting up our project using SceneDelegate instead of AppDelegate. More specifically, you want to leave AppDelegate alone and instead make the following changes in SceneDelegate:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {    var window: UIWindow?        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {        if let windowScene = scene as? UIWindowScene {            let window = UIWindow(windowScene: windowScene)            window.rootViewController = MainTabBarController()            self.window = window window.makeKeyAndVisible()        }    }}

Comments (47)
RaVeN_BA
6 years ago
Can you provide all assets in a separate archive?
Brian Voong
6 years ago
ansonngch
5 years ago
Hi Brian, have you updated the website? I can't find any suitable images for the icons online
Brian Voong
5 years ago
Jesus Adolfo
6 years ago
HOLY MOLY BRIAN. I didn't know you could drag away breakpoints to delete them. Cool trick
perry1732
5 years ago
thumbs up
hyun kim
6 years ago
Hi.. I don'k now how current user's uid can get that time. coz we didn't make login page...
Brian Voong
6 years ago
hyun kim
6 years ago
Than you Brian.. I got it..
junkain
6 years ago
Hi Brian !!! Thanks for awesome courses, i have a question.... why i can not see username on titile , it just uid like NVJ3O9U6NHQpxxqxpPjrOTmkv653...
Brian Voong
6 years ago
Stephen Novotny
6 years ago
Great as always. Brian: snapshot.value as? NSDictionary vs snapshot.value as? [String: Any] pros/cons, should I care?
Brian Voong
6 years ago
Alaric
6 years ago
Hi Brian, I was following along up to the point where we add the MainTabBarController to AppDelegate, and then I got stuck. When I first set up the project, I followed the instructions from your Kindle Basic Training course to remove Main.storyboard. I found that the only way for me to get the blue window in this video is to add the storyboard back to the project, along with adding "Main" back to Deployment Info --> Main Interface. I'm not sure how or why it works like this; can you explain this to me? Thank you so much!
mattnet
6 years ago
Probably most satisfying video yet as we now know how to query firebase database to display things....great session!
wasim
6 years ago
I was wondering, Should I implement UI programmatically without using storyboard in real world applications? I think using the programmatic approach in learning is very important to understand the basics and how everything work, but in real world applications, i may try to use storyboard to save time and effort, so i focus on business logic. What do you think Mr. Brain ? Is that the way to go or you prefer other approach ?
Brian Voong
5 years ago
digimarktech
6 years ago
Brian, first of all awesome work and great vid! Small question: At the very end of the video you did not use a guard statement on the username variable. While i understand that we have unwrapped the dictionary using guard statement, i would have expected the username variable to be optional because of the down casting as a optional string. So when you print username to the console, it is optional, but when displayed in the navigation title, it is not. What magic is apple doing behind the scenes? lol
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
smiller193
6 years ago
Is anyone having an issue with the input accessory view getting stuck at the bottom? When exiting comment screen
Brian Voong
5 years ago
Adam El-Kadi
5 years ago
Brian, I have a question can you teach us how to make a like page? What I mean by that is when I ran your complete project, the likes/notifications page was empty. Can you teach up how to fix that and how when someone comments or likes my photo I recieve a notification
Brian Voong
5 years ago
Tokyojogo
5 years ago
Hi Brian, great vid. I have a question though. Regarding the Navigation controller, why was it set inside the tabbarcontroller and not inside userprofilecontroller? Does it make a difference on where it is placed? What if not all the tabs will have a nav controller (i'm referring to the top nav bar in case I got it wrong). Thanks.
Brian Voong
5 years ago
Tokyojogo
5 years ago
children controller = userProfileController?
Brian Voong
5 years ago
iHobbit
5 years ago
Mundane question. When you use an image asset by name in the latest version of Xcode, it only shows the thumbnail image, unlike your setup where you see the image name and the thumbnail. I know you can do UIImage(named: "foo") to fix this, but is there a setting somewhere in the editor to change this behavior? Thanks!
Brian Voong
5 years ago
Pawel Nowak
5 years ago
Hi Brian. I try to learn your course on new xcode and swift. I have error with override func in MainTabBarController. When I delete override, I haven't got error but func doesn't work.
Brian Voong
5 years ago
Pawel Nowak
5 years ago
Ok i will try it, but when i have override word, I have error: Method does not override any method from its superclass. I get back to you when i test your project.
Pawel Nowak
5 years ago
Ok, it works fine. I copy your file MainTabBarController.swift - I think I had a typo, but I checked it a dozen times before I wrote;)
johnsoa7
5 years ago
Hi Brian, great course and videos! I was wondering why even though I've already made the sign up page and signed in users, how come no username, not even the uid is showing in the navigation title?
johnsoa7
5 years ago
I've fixed it!
ducward
5 years ago
Can you explain how you solved this problem? I am having the same problem with the user/uid not showing up in the navigation title
Kevin Amador
5 years ago
Wow, nice class Brian, congrats.
Gabriel Seben
5 years ago
Hi, Congratulations on class, fine. I'm adapting you tube lessons on mensager to those of instagram. I'm having trouble collecting the index path of a colectionview, I hope you can help me. @objc func deleteSelectdItemAction (_ sender: AnyObject?) {                 if let IndexPaths = collectionView? .indexPathsForSelectedItems {             for IndexPath in IndexPaths {                 if cell = collectionView? .cellForItem (at: IndexPath) CustomerCell {                     print (cell)                 }             }         }                  // reference (to: .clients) .document ("SrZr1cg0LT1nSPiWBp7E"). delete ()              } ===================================================== I need to retrieve the unique identifier of the firebase "SrZr1cg0LT1nSPiWBp7E" which in the case is relative of the query that I am doing This is the result, but I want to access this value: SrZr1cg0LT1nSPiWBp7E <ClinicalClearCell: 0x7f84c2c62270; baseClass = UICollectionViewCell; frame = (0 320; 414 100); layer = <CALayer: 0x6040002331a0 >> How can I do it?  In your courses there is no example that shows how to delete an item from the collection view, this is a failure of your courses
Brian Voong
5 years ago
Gabriel Seben
5 years ago
It's ok But how do I do this from a common function? I'm not using a collection view event @objc func deleteSelectdItemAction (_ sender: AnyObject?) {      // How to retrieve an indexPath from this point, that's the question } In fact I'm pretty lost, you could have fianlizado this knowledge when talking about collections in messenger classes. Because the issue is not only to delete the element but rather to work the layout so that the checkbox appears dynamically next to the cell when clicking on the deletion as well as the in the wathsaap application
Gabriel Seben
5 years ago
It's ok But how do I do this from a common function? I'm not using a collection view event @objc func deleteSelectdItemAction (_ sender: AnyObject?) { // How to retrieve an indexPath from this point, that's the question } In fact I'm pretty lost, you could have fianlizado this knowledge when talking about collections in messenger classes. Because the issue is not only to delete the element but rather to work the layout so that the checkbox appears dynamically next to the cell when clicking on the deletion as well as the in the wathsaap application
Gabriel Seben
5 years ago
What I need to rescue is the parent I need to redeem the document code
Craig Jarman
5 years ago
Just curious. And maybe this will be answered at a later point. If there was no network connection does the application error?
Brian Voong
5 years ago
AlfieLBTA
5 years ago
Hey Brian and classroom folks , is anyone kind enough to explain why on the dictionary unwrapping thing : guard let dictionary = snapshot.value as?[String: Any] else { return } let username = dictionary["username"] as? String we had -> dictionary?["username"] instead of -> dictionary["username"]! before the guard statement? Whats the purporse of the ? after the dictionary word, don't you force unwrap with the "!" ?
Brian Voong
5 years ago
masonbose
5 years ago
Hey Brian, When I try to retrieve the user name, the Xcode console prints out <null>. I have no idea why, and copied your code. fileprivate func fetchUser() { guard let uid = Auth.auth().currentUser?.uid else { return } Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in print(snapshot.value ?? "") }) { (err) in print("Failed to fetch user:", err) } } Any idea why it prints <null>? Thanks
Brian Voong
5 years ago
PreachOnBerto
5 years ago
I have the same issue. I'm am able to get the uid to display without the fetchUser() function, but when I do use fetchUser() to get the username, I get a <null> value printed in the console.
PreachOnBerto
5 years ago
I went forward to see if I could get the User's profile image but nothing again. I used a break point at where we would call: guard let dictionary = snapshot.value as? [String : Any] else { return } on the left side of the debug cole, it says the dictionary is empty. I'm sure I am referencing the correct nodes of child("users").child(uid), but I'm not sure why I can't get the values from Firebase.
Duc Dang
5 years ago
Hi Bryan, I'm having 2 issues rn 'FirebaseCore/FirebaseCore.h' file not found Could not build Objective-C module 'Firebase' I tried this: Quit Xcode. Delete project's temp files located at ~/Library/Developer/Xcode/DerivedData Delete ProjectName.xcworkspace Delete Podfile.lock file and Pods folder Run pod install. Open the newly created ProjectName.xcworkspace file and build. or pod update or anything I can with google search. I'm not sure what cause the issue Its really complicated and I do not have enough time( I do not really want to) to start over. Any suggestion?
Duc Dang
5 years ago
oh okey, so I solved these problems by deleted everything in Xcode/DerivedData. I was able to make a successful build but the app wont work and the console says : libc++abi.dylib: terminating with uncaught exception of type NSException (lldb) and the debug alert says : Thread1: signal SIGABRT
Duc Dang
5 years ago
and if I replace the GoogleService-Info.plist by another file, the app no longer blank and work perfectly except registed user wont show up at Firebase Authentication
Duc Dang
5 years ago
*replace the GoogleService-Info.plist by a new GoogleService-Info.plist
Duc Dang
5 years ago
I'm so sorry for spamming, but it seems like everytime I post a question, I will soon find the solution. I solved it, everything works perfectly now. Please delete all of the comment if its disturbing the channel! Peaces out!
Duc Dang
5 years ago
my Xcode wont let me do the same as you do at 8:52 let userProfileController = UserProfileController(collectionViewLayout: layout) --> Incorrect argument label in call (have 'collectionViewLayout:', expected 'coder:') please help!
Brian Voong
5 years ago
Duc Dang
5 years ago
heyyyy, I replaced 'collectionViewLayout' with 'coder' and it says: --> Cannot convert value of type 'UICollectionViewFlowLayout' to expected argument type 'NSCoder' I also checked your files, copy&paste everything from your MainTabBarController.swift to mine but the error still there I'm really new to apps dev, everything I did basically was following your steps...
Brian Voong
5 years ago
Duc Dang
5 years ago
For the love of god, it turns out that I misspelled class UserProfileController: UICollectionViewController in UserProfileController.swift Thank you very much!!! mah man!
Tokyojogo
5 years ago
Hey brian, Question, are there changes in xcode/swift that's affecting the main.storyboard? I can't seem to delete it from the general tab. I deleted the main.storyboard file then tried deleting main from the general tab but everytime I run it, it keeps crashing and when I look at the error, its looking for "main" in the bundle and when I click on the general tab again, its there even after just deleting it. I tried deleting it then clicking on a different file (viewcontroller) then when I click on general again, its there. I tried doing a new project and doing that first and I'm getting the same thing. Any thoughts?
Tokyojogo
5 years ago
nvm, I solved it. Its not deleting in the general tab. I had to delete it in the plist file.
Pat Trudel
5 years ago
If any other students are having issues on lesson 5, solution below. After creating the UIWindow in the App delegate, "window = UIWindow() window?.rootViewController = MainTabBarController()" Was not sufficient to display the MainTabBarController(). After doing some research I found that you can simply fix this by adding this line of code below "window?.makeKeyAndVisible()" Brian, do you have any idea why I needed to specify this? I assume it is because I have deleted my storyboard? Thank you
Brian Voong
5 years ago
Pat Trudel
5 years ago
Thank you for the prompt response, I'll be sure to always include that from now on.
Sebbie
5 years ago
Hey Brian, I'm having a problem trying to fetch user... I'm getting the following error: Error Domain=com.firebase Code=1 "Permission Denied" UserInfo={NSLocalizedDescription=Permission Denied} I've looked in Firebase docs but cannot seem to find what I'm looking for (or maybe I just don't understand it yet). In Firebase Storage, I left the default rules at: service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write: if request.auth != null; } } } Do I need to change the rules, or is my problem somewhere else?
Brian Voong
5 years ago
Sebbie
5 years ago
All fixed! You know what, I was just being stoopid :) I didn't notice I had deleted the piece of code that saved user info!!! That's what you get for trying to learn something while helping everyone around. I have to say, so far your course is perfect!!! Thanks again, Brian :D
ducward
5 years ago
Hey Brian, I am trying to add breakpoints like you did in the video to see if there's data coming in from the database. The console is outputting "unable to read data" for the uid as opposed to the actual uid of the user. Do you have suggestions to fix this problem? Thank you.
arian
5 years ago
Hi ducward, after the App being stopped on the breakPoint, u need to type : po snapshot.value in xcode debugger you will the the whole dictionary of key value for that particular node
theebrendanjohnson
5 years ago
Hey Brian, I'm having an issue where i'm unable to fetch the Username from Firebase. class UserProfileController: UICollectionViewController, UICollectionViewDelegateFlowLayout { override func viewDidLoad(){ super.viewDidLoad() collectionView?.backgroundColor = .white navigationItem.title = Auth.auth().currentUser?.uid fetchUser() I'm unable to see the username in the navController. it worked when I tried just navigationItem.title = "User Profile" but just not when i'm connecting to firebase using Auth.auth().currentUser?.uid I tried using Auth.auth()?.currentUser?.uid but that gives me the error of "Cannot use optional chaining on non-optional value of type 'Auth' Replace '?' with " " Which then that put's me right where I was before unfortunately. If you or anyone could help me out that would be much appreciated. Thank You.
hudsonpereira
5 years ago
Hey friend, you actually won't get the username from the Auth library, but the Database rather So you have to use Database.database().reference().child("users).child(user.uid).observe... to get the right node, than cast it to the dictionary hope it helps
Osioreame
5 years ago
Hey there, I'm having the same problem and I just noticed you used child(user.uid) in your proposed fix while I only used "child(uid)" but when I tried to put that I got the error "Use of unresolved identifier 'user'". Is there any other way around this issue?
esong2288
5 years ago
There seems to be almost a one second delay before the username pops up in the title bar. I don't think it's the internet since I've run the app in multiple locations. Could this delay have something to do with code or with my database?
Brian Voong
5 years ago
esong2288
5 years ago
Oh ok that's a relief, thanks!
joker45
5 years ago
----- here it's just a small shortcut ---- Hey @Brian & all, if you want add a NEW FILE / Class, than just use: FILE -> NEW -> File -> Cocoa Touch Class -> than name it like your Example "MainTabBarController" and make it Subclass of: "UITabBarController" (or what for subclass needed) Than you get directly an file with Import UIkit, correct class definition and viewDidLoad... and dont lose time :-)
dclawson
5 years ago
Interesting, that does work. I was worried that it wouldn't end up as a .swift file, but the option is right there. Thanks for the tip!
dclawson
5 years ago
Dumb question: does using "fileprivate" block you from accessing that method if you were to write an extension to the UserProfileController class in another file?
Brian Voong
5 years ago
Drew Staz
5 years ago
Hi Brian where's the best source to get good icon images?
Brian Voong
5 years ago
beto123
4 years ago
Great Stuff!
jwaples
4 years ago
In the LinkedIn app, when you click a tabBar icon, there’s a good animation where the menu icon is colored from the center to the edges. It would be cool to learn the tricks of that animation!
PatrickVB
4 years ago
Under the heading: "Is It Just Me". I am running through this lesson while building another App and when trying to present the Tab Bar Item (icon) I now Have-To provide a Let statement above calling the icon?! Is that something NEW in Xcode 10?? Thanks! -Patrick let home_selected = UIImage(named: "home_selected") let home_unselected = UIImage(named: "home_unselected") navController.tabBarItem.image = home_unselected navController.tabBarItem.selectedImage = home_selected
Ayub9992
4 years ago
Its pretty simple in Xcode 10 what ever image you want just type in for example let image = image[literal]. That click on the icon provided it will give you access to all the icon assets that exist in you project
anantangad
4 years ago
Hello Brian, The Username is not showing up on my navigation bar. I get the string "User Profile" but never get the username on the bar. Any help would be appreciated. Thanks
Brian Voong
4 years ago
Ayub9992
4 years ago
Hello got a quick question again. When we are getting the user data snapshot how does it know what we want. In the tree we have both the username and the user profile image right? So when we did fileprivate func fetchUser(){ guard let uid = Auth.auth().currentUser?.uid else { return } Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { (DataSnapshot) in print(DataSnapshot.value ?? "") }) { (err) in print("Failed to print out user") } } This how did it know to go for the username other than the user profile image?
Ayub9992
4 years ago
Nevermind, I figured it out is a snapshot so it provides a dictionary type of everything within the data snapshot including images in the database. Otherwise specified
Brian Voong
4 years ago
Copytan
4 years ago
Howdy! I was wondering if there is a map VC that I can call? In instagram you can display your location when you take a picture and look on maps to see where it is. In the beginning of this video you set up all of your controllers such as navigation controller and I was wondering is there a way to call apple maps? Instead of using the storyboard, because that's the only way I know how to do it.... Any help would be greatly appreciated! Thanks you.
Brian Voong
4 years ago
arturfil@hotmail.com
4 years ago
Hi Brian, I have been trying resolve this problem and maybe it's something very simple but I can't figure out what is the cause of my problem. I can't seem to be able to select the images in the Assets in my MainTabController, I tried to see if people had problems with this too but I didn't find anything, also I googled in Stack Overflow and also didn't find much.. I can't seem able to set the profile_selected and profile_unselected image in the navController. Is there something that I can do to fixed this? Thanks in advance.
moustafa gadallah
4 years ago
link to download the project ?
Ahmed.Q
4 years ago
Hello Brian, Since you mostly speak about two or three topics in one video like this one, we have first how to implement root controller and fetching user, I suggest you mark the begging of the next topic with a slide or whatever just to make it easy to navigate through the video. Hope I have my point clear .
hflournoy
4 years ago
Hi Brian, I believe this is a Firebase issue. I am not getting the UN to show up, but instead the long string. (1.) all reference code is exact (2.) I am logged in to Firebase (3.) Again, in the newest version of Firebase, it appears that they make you configure your own database (even for the legacy "Real Time Database") so this could be the problem as well. Here is my output: 2019-09-19 19:25:11.548069-0500 ******[4338:-------] - <AppMeasurement>[I-ACS036002] Analytics screen reporting is enabled. Call +[FIRAnalytics setScreenName:setScreenClass:] to set the screen name or override the default screen class name. To disable screen reporting, set the flag FirebaseScreenReportingEnabled to NO (boolean) in the Info.plist 2019-09-19 19:25:11.764502-0500 MomLikes[4338:701064] 6.8.0 - [Firebase/Analytics][I-ACS023007] Analytics v.60101000 started 2019-09-19 19:25:11.771441-0500 MomLikes[4338:701064] 6.8.0 - [Firebase/Analytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see http://goo.gl/RfcP7r) <null> 2019-09-19 19:29:43.522563-0500 MomLikes[4338:704987] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C2.1:2][0x7fb30be3d450] get output frames failed, state 8196 2019-09-19 19:29:43.523888-0500 MomLikes[4338:704987] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C2.1:2][0x7fb30be3d450] get output frames failed, state 8196 2019-09-19 19:29:43.525730-0500 MomLikes[4338:704987] TIC Read Status [2:0x0]: 1:57 2019-09-19 19:29:43.526520-0500 MomLikes[4338:704987] TIC Read Status [2:0x0]: 1:57 Any thoughts? Champe
Michael Law
3 years ago
here's my updated code for Xcode 11, in SceneDelegate func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: windowScene) window?.rootViewController = MainTabBarController() }
HappyCow
3 years ago
Thanks, helped me out.
ok31719
3 years ago
Hi Brian, I tried to set the rootViewController as a MainTabBarController and it keep start at ViewController when I run the project. I am using Xcode 11.2 and swift 5 and there are SceneDelegate and AppDelegate which UIwindow is located at SceneDelegate and I try to figure it out and I don't know yet. Any help would be appreciated. Thanks
Brian Voong
3 years ago
ZacharySmouse
3 years ago
Hi Brian, I'm setting up the UserProfile and I'm getting two navigation bars. The title is on the second nav bar as well. Is there a fix to this? Thanks!
HELP & SUPPORT