I have implemented a login to load data from a real-time database every time a user logs in. When the user has successfully logged in, the data is being read - the problem is that AppDelegate changes the ViewController faster than the data is being read. Therefore, nothing will be displayed until the app is closed again.
Is there a way to delay the change of the view until the data is read?
didFinishLaunchingOptions() inside AppDelegate:
let authListener = Auth.auth().addStateDidChangeListener { auth, user in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if user != nil {
let controller = storyboard.instantiateViewController(withIdentifier: "RootPageViewController") as! RootPageViewController
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
} else {
let vc = storyboard.instantiateViewController(withIdentifier: "SettingsTableViewController") as! SettingsTableViewController
vc.runResetData()
let controller = storyboard.instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileViewController
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
}
}
LoginViewController:
#IBAction func login(_ sender: Any) {
guard let email = emailInput.text else { return }
guard let password = passwordInput.text else { return }
Auth.auth().signIn(withEmail: email, password: password) { user, error in
if error == nil && user != nil {
self.readData()
self.dismiss(animated: false, completion: nil)
} else {
print("Error logging in: ", error!.localizedDescription)
let alert = UIAlertController(title: "Fehler beim Einloggen", message: error!.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Verstanden", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
func readData() {
guard let uid = Auth.auth().currentUser?.uid else { return }
let databaseRef = Database.database().reference()
databaseRef.child("users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let monthlyStartKmData = value?["monthlyStartKm"] as? Int ?? 0
let currentKmData = value?["currentKm"] as? Int ?? 0
...
startKm = monthlyStartKmData
currentKm = currentKmData
...
}) { (error) in
print(error.localizedDescription)
}
}
No you can't as the call to listen is asynchronous so it's run with a delay while the rootVC is setted , you need to show A loader like
let vc = UIViewController()
vc.view.backgroundColor = .red
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
let authListener = Auth.auth().addStateDidChangeListener { auth, user in
.....
}
Inside AppDelegate
if FIRAuth.auth().currentUser != nil {
// go to home , if you went before you should have km month values cached
}
else {
// go to login
}
There's a possibility to delay the change of view until Firebase was able to load its data:
databaseRef.observeSingleEvent
Working code:
let authListener = Auth.auth().addStateDidChangeListener { auth, user in
let databaseRef = Database.database().reference()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if user != nil {
databaseRef.observeSingleEvent(of: .value, with: { snap in
let controller = storyboard.instantiateViewController(withIdentifier: "RootPageViewController") as! RootPageViewController
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
})
} else {
let vc = storyboard.instantiateViewController(withIdentifier: "SettingsTableViewController") as! SettingsTableViewController
vc.runResetData()
let controller = storyboard.instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileViewController
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
}
}
Related
i created a sign in with google feature, and everything is working with the signing in with the firebase and authentication. my problem is that after a successful sign in i want the app to move to a differnent page/controller from the app delegate.
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewController: SigninViewController = storyboard.instantiateViewController(withIdentifier: "GoogleTabController") as! SigninViewController;
// Then push that view controller onto the navigation stack
let rootViewController = self.window!.rootViewController as! UINavigationController;
rootViewController.pushViewController(viewController, animated: true);
is giving me an error that reads "could not cast value of type uitabbarcontrller to signinViewcontroller"
here is my full code:
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
accessToken: authentication.accessToken)
let number = Int.random(in: 0..<100)
let numberString = String(number)
let db = Firestore.firestore()
let googleName = user.profile.name
let googleEmail = user.profile.email
let googleUsername = user.profile.name+numberString
let country = ""
let bio = ""
let profImg = user.profile.imageURL(withDimension: 100)?.absoluteString
let password = ""
Auth.auth().signInAndRetrieveData(with: credential) { (authResulft, error) in
if let error = error{
print(error)
}else{
let userid = Auth.auth().currentUser!.uid
db.collection("users").whereField("uid", isEqualTo: userid).getDocuments(){querySnapshot, error in
if let error = error {
print(error.localizedDescription)
}else
{
if querySnapshot!.isEmpty{
db.collection("users").document(userid).setData([
"name": googleName!,
"username": googleUsername,
"email": googleEmail!,
"password": password,
"uid": userid,
"country": country,
"bio": bio,
"profileImage": profImg!,
]) { err in
if err != nil {
} else {
print("logged in success and db stored")
//below code doesnt work
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewController: SigninViewController = storyboard.instantiateViewController(withIdentifier: "GoogleTabController") as! SigninViewController;
// Then push that view controller onto the navigation stack
let rootViewController = self.window!.rootViewController as! UINavigationController;
rootViewController.pushViewController(viewController, animated: true);
}
}
}else{
//here perform segue
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewController: SigninViewController = storyboard.instantiateViewController(withIdentifier: "GoogleTabController") as! SigninViewController;
// Then push that view controller onto the navigation stack
let rootViewController = self.window!.rootViewController as! UINavigationController;
rootViewController.pushViewController(viewController, animated: true);
}
}
}
}
}
}
The problem is here
let viewController: SigninViewController = storyboard.instantiateViewController(withIdentifier: "GoogleTabController") as! SigninViewController;
GoogleTabController is a tabViewController not SigninViewController you need to use
let viewController = storyboard.instantiateViewController(withIdentifier: "GoogleTabController")!
I am trying to go to "inbox" tab when I clicked on the notification.
This is the notificationManager:
func didReceiveNotification(notif: [AnyHashable : Any]) {
print("notification... \(notif)")
guard let msgData = notif["gcm.notification.messageData"] as? String else {
return
}
print("msgData: \(msgData)")
CommandManager.shared.processNotification(msgData)
}
This is the commandManager:
func processNotification(_ commands: String) {
var dict:[String:Any] = [:]
dict = dict.convertToDictionary(text: commands) ?? [:]
print("dict \(dict)")
sendMessageToFirestore(data: dict)
let inbox = EngageViewController()
//present the inbox tab
}
Use rootViewController
func processNotification(_ commands: String) {
var dict:[String:Any] = [:]
dict = dict.convertToDictionary(text: commands) ?? [:]
print("dict \(dict)")
sendMessageToFirestore(data: dict)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "inboxPage") as! UIViewController
UIApplication.shared.keyWindow?.rootViewController = viewController
}
Edit
If it's a UITabBarController, use:
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
viewcontroller.selectedIndex = 1 //index of your inbox
UIApplication.shared.keyWindow?.rootViewController = viewController
If the initial view of app is TabBarController then you can do something like in
AppDelegate.swift
guard let tabBarController = self.window?.rootViewController as? UITabBarController else {
return
}
so,
tabBarController.selectedIndex = 1 //Whatever the index of inbox is
Im creating a profile for my app and when Im trying to delete the profile it won't delete from the view if I come back to it, In the other hand if I close the app and open it again the data would be gone. I can see the data been removed from the sqlite Database in my simulator.
override func viewDidLoad() {
super.viewDidLoad()
showDatePicker()
showPickerRanks ()
pickerRank.delegate = self
pickerRank.dataSource = self
sideMenus()
let appDelegate = UIApplication.shared.delegate as! AppDelegate // UIApplication.shared().delegate as! AppDelegate is now UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Profile")
request.returnsObjectsAsFaults = false
var isEmpty : Bool {
do {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Profile")
let count = try context.count(for: request)
return count == 0 ? true : false
} catch {
return true
}
}
if isEmpty == true {
//Check if there is a Profile
performSegue(withIdentifier: "NoProfileSegue", sender: nil)
} else {
print("No Files")
}
print("Database is empty:\(isEmpty)")
do {
let results = try context.fetch(request)
for result in results as! [NSManagedObject] {
if let airmanNameVar = result.value(forKey: "airmanName") as? String {
PersonName.text = airmanNameVar
}
if let airmanRankVar = result.value(forKey: "airmanRank") as? String {
AirmanRankPicker.text = airmanRankVar
}
if let airmanHeigthVar = result.value(forKey: "airmanHeight") as? Double {
HeightTxtLbl.text = String (airmanHeigthVar)
}
if let airmanWeightVar = result.value(forKey: "airmanWeight") as? Int64 {
weightTxtLbl.text = String (airmanWeightVar)
}
if let airmanAFPTScore = result.value(forKey: "airmanLastAFPTScore") as? Double {
LastAFPTScore.text = String(airmanAFPTScore)
}
if let airmanAFPTDateLast = result.value(forKey: "airmanLastAFTPData") as? String {
LastAFPTDate.text = airmanAFPTDateLast
}
and here is my Delete
#IBAction func DeleteBtn(_ sender: Any) {
let actionSheetController: UIAlertController = UIAlertController(title: "AF Fitness", message:"By pressing Delete all data would be erase.", preferredStyle: .actionSheet)
//Create and add the Cancel action
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) { action -> Void in
}
actionSheetController.addAction(cancelAction)
let AgreeAction: UIAlertAction = UIAlertAction(title: "Delete", style: .default) { action -> Void in
self.resetAllRecords(in: "Profile")
self.deleteHistory()
UserDefaults.standard.set(false, forKey: "ProfileOn") //Bool Data Type
UserDefaults.standard.synchronize()
self.AgeGroupSeg.selectedSegmentIndex = 0
self.GenderSeg.selectedSegmentIndex = 0
UserDefaults.standard.set(0, forKey: "GenderData")
UserDefaults.standard.set(0, forKey: "AgeGroupData")
self.AirmanRankPicker.text = ""
self.PersonName.text = ""
self.weightTxtLbl.text = ""
self.HeightTxtLbl.text = ""
self.LastAFPTDate.text = ""
self.LastAFPTScore.text = ""
self.performSegue(withIdentifier: "NoProfileSegue", sender: nil)
// self.performSegue(withIdentifier: "NoProfileSegue", sender: nil)
}
actionSheetController.addAction(AgreeAction )
//Present the AlertController
self.present(actionSheetController, animated: true, completion: nil)
}
func resetAllRecords(in entity : String) // entity = Your_Entity_Name
{
let appDelegate = UIApplication.shared.delegate as! AppDelegate // UIApplication.shared().delegate as! AppDelegate is now UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Profile")
request.returnsObjectsAsFaults = false
let deleteRequest = NSBatchDeleteRequest(fetchRequest: request)
do {
try context.execute(deleteRequest)
try context.save()
} catch {
print ("There was an error")
}
}
Thank you in advance
I am developing an app in which I have login page and dashboard page in login page user can login with facebook,after login I navigate the user to dashboard everything works fine till now
But in dashboard I am going to add side menu (by using SWRevealViewcontroller) If I give swrevealviewcontroller as intialView It works but I could not see the login page
First I have to bring login page then it should move to dashboard(which contains side menu item). Here I am using two navigationControllers one is to login and another one is for swrevealViewcontroller
I don't know how to move from login page to dashboard (which contains side menu item) now
This is my app delegate
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject:AnyObject]?) -> Bool {
// Override point for customization after application launch.
print("at delegate")
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
GIDSignIn.sharedInstance().delegate = self
if NSUserDefaults.standardUserDefaults().boolForKey("kUserLogin")
{
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let root:UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("RevealView")
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = root
self.window?.makeKeyAndVisible()
}
else
{
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("loginView") as UIViewController
let nav:UINavigationController = UINavigationController.init(rootViewController: initialViewControlleripad)
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = nav
self.window?.makeKeyAndVisible()
}
return FBSDKApplicationDelegate.sharedInstance().application(application,
didFinishLaunchingWithOptions:launchOptions) || true
}
this is my loginbutton function
func loginButton(loginButton: FBSDKLoginButton!,didCompleteWithResult result : FBSDKLoginManagerLoginResult!, error: NSError!)
{
print("come to ")
FBSDKGraphRequest.init(graphPath: "me", parameters: ["fields":"name,picture.type(large),gender,email"]).startWithCompletionHandler { (connection, result, error) -> Void in
print("come to print")
let strName: String = (result.objectForKey("name") as? String)!
print("before getting token")
var token = FBSDKAccessToken.currentAccessToken().tokenString
print(token)
print("after getting token")
print(result)
let Gender : String = (result.objectForKey("gender") as? String)!
let Id = (result.objectForKey("id") as? String)!
let deviceId = UIDevice.currentDevice().identifierForVendor?.UUIDString
let UUID = NSUUID().UUIDString
print(UUID)
var DeviceId = deviceId
print(DeviceId)
print(Id)
print(Gender)
print(strName)
var strEmail : String
if ((result.objectForKey("email") as? String) != nil){
strEmail = (result.objectForKey("email") as? String)!
}else {
strEmail = "not available"
}
//let strEmail: String = (result.objectForKey("email") as? String)!
var userID = result["id"] as! NSString
var facebookProfileUrl = "http://graph.facebook.com/\(userID)/picture?type=large"
// print(strEmail)
let request = NSMutableURLRequest(URL: NSURL(string: "http://projects.svirtzone.com/wified/api/authentication.php")!)
request.HTTPMethod = "POST"
let postString = "username=\(strName)&email=\(strEmail)&action=auth&pic=\(facebookProfileUrl)&dob=1989/05/05&logintype=Facebook&gender=\(Gender)&device_type=Mac&facebookid=\(Id)&agerange=15&deviceid=\(deviceId)&accesstoken=\(token)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard error == nil && data != nil else { // check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
task.resume()
}
if(error != nil){
print(error.localizedDescription)
return
}
print("before main view")
let defaults = NSUserDefaults.standardUserDefaults()
if !defaults.boolForKey("kUserLogin")
{
print("inside if***")
defaults.setBool(true, forKey: "kUserLogin")
}
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "kUserLogin")
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("RevealView") as UIViewController
let nav:UINavigationController = UINavigationController.init(rootViewController: initialViewControlleripad)
app.window = UIWindow(frame: UIScreen.mainScreen().bounds)
app.window?.rootViewController = nav
app.window?.makeKeyAndVisible()
}
this is my main viewController(I set this with swrevealViewController) here I have side menu item "Menu" this Item is disabling now
#IBOutlet var Menu: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
Menu.target = self.revealViewController()
Menu.action = Selector("revealToggle:")
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
this is my google signIn code in appDelegate
func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!,
withError error: NSError!) {
if (error == nil) {
print("at delegate5")
// Perform any operations on signed in user here.
let userId = user.userID // For client-side use only!
let idToken = user.authentication.idToken // Safe to send to the server
let fullName = user.profile.name
let givenName = user.profile.givenName
let familyName = user.profile.familyName
let email = user.profile.email
var imageURL = ""
if user.profile.hasImage {
imageURL = user.profile.imageURLWithDimension(100).absoluteString
}
NSNotificationCenter.defaultCenter().postNotificationName(
"ToggleAuthUINotification",
object: nil,
userInfo: ["statusText": "Signed in user:\n\(fullName)","email" : email, "imageURL" : imageURL])
print( imageURL)
let postString = "username=\(fullName)&email=\(email)&action=auth&pic=\(imageURL)&dob=1989/05/05&logintype=Google&gender=female&device_type=Mac&facebookid=no&agerange=15&deviceid=not available&accesstoken=\(idToken)"
let request = NSMutableURLRequest(URL: NSURL(string: "http://projects.svirtzone.com/wified/api/authentication.php")!)
request.HTTPMethod = "POST"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard error == nil && data != nil else { // check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
task.resume()
} else {
print("\(error.localizedDescription)")
NSNotificationCenter.defaultCenter().postNotificationName(
"ToggleAuthUINotification", object: nil, userInfo: nil)
let defaults = NSUserDefaults.standardUserDefaults()
if !defaults.boolForKey("kUserLogin")
{
print("inside if***")
defaults.setBool(true, forKey: "kUserLogin")
}
}
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "kUserLogin")
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("RevealView") as UIViewController
let nav:UINavigationController = UINavigationController.init(rootViewController: initialViewControlleripad)
app.window = UIWindow(frame: UIScreen.mainScreen().bounds)
app.window?.rootViewController = nav
app.window?.makeKeyAndVisible()
}
Can any one help me please ?
Try this I hope it would be helpful!!!
After the login successfully set flag value in LoginViewController
let defaults = NSUserDefaults.standardUserDefaults()
if !defaults.boolForKey("kUserLogin")
{
defaults.setBool(true, forKey: "kUserLogin")
}
When You log out set the flag value and make Login Screen as root
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "kUserLogin")
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("LoginViewController") as UIViewController
let nav:UINavigationController = UINavigationController.init(rootViewController: initialViewControlleripad)
app.window = UIWindow(frame: UIScreen.mainScreen().bounds)
app.window?.rootViewController = nav
app.window?.makeKeyAndVisible()
Step-2 Set Rootviewcontroller as SVrevealviewcontroller
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if NSUserDefaults.standardUserDefaults().boolForKey("kUserLogin")
{
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let root:UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("RootViewController")
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = root
self.window?.makeKeyAndVisible()
}
else
{
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("LoginViewController") as UIViewController
let nav:UINavigationController = UINavigationController.init(rootViewController: initialViewControlleripad)
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = nav
self.window?.makeKeyAndVisible()
}
return true
}
I have begun building an app that lets a user sign up and create a family. Right now I am downloading the data for the user from the log in screen and, from the appDelegate if the user is already logged in. However, when the user data is downloaded from the appDelegate I get nil values.
Whats weird is that I have the following written in each of my three view controllers(controlled by a tab controller):
var user: User? {
didSet {
print(user!.name!)
}
}
When the data eventually downloads from the appDelegate the correct name is printed. However, trying to use the user variable at any other time gives nil.
Also, when the data is downloaded from the log in screen it works perfectly. Very confused about this and would hugely appreciate any help. Thanks in advance.
I figured out what was wrong. Nothing to do with firebase.
While in the app delegate after downloading the user data, I tried to set the properties of the viewControllers in my tabViewController. What I actually did was create a new instance of each view controller, set its properties(which is why the didSet property observer fired) but then when setting the rootViewController I created a new instance of the tabController which I think then created new instances of the three viewControllers.
This is what the old code was in the appDelegate:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
if let user = FIRAuth.auth()?.currentUser {
downloadUserData(user)
self.window?.rootViewController = storyBoard.instantiateViewControllerWithIdentifier("Home")
} else {
window?.rootViewController = storyBoard.instantiateViewControllerWithIdentifier("SignIn")
}
return true
}
func downloadUserData(user: FIRUser) {
let ref = FIRDatabase.database().reference()
ref.child("users").queryOrderedByKey().queryEqualToValue(user.uid).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
for child in snapshot.children {
if let name = child.value!["name"] as? String, let familyID = child.value!["signedInTo"] as? String {
self.user = User(uid: user.uid, name: name)
ref.child("families").queryOrderedByKey().queryEqualToValue(familyID).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
for child in snapshot.children {
if let name = child.value!["name"] as? String {
self.family = Family(uid: familyID, name: name)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let tabVC = storyBoard.instantiateViewControllerWithIdentifier("Home") as? TabBarViewController
tabVC?.user = self.user
tabVC?.family = self.family
let choresNav = tabVC?.viewControllers![0] as? UINavigationController
let choresVC = choresNav?.topViewController as? ChoresViewController
choresVC?.user = self.user
choresVC?.family = self.family
}
}
})
}
}
})
}
This is the appDelegate now, along with a custom TabBarViewController:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
if let user = FIRAuth.auth()?.currentUser {
downloadUserData(user)
} else {
window?.rootViewController = storyBoard.instantiateViewControllerWithIdentifier("SignIn")
}
return true
}
func downloadUserData(user: FIRUser) {
let ref = FIRDatabase.database().reference()
ref.child("users").queryOrderedByKey().queryEqualToValue(user.uid).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
for child in snapshot.children {
if let name = child.value!["name"] as? String, let familyID = child.value!["signedInTo"] as? String {
self.user = User(uid: user.uid, name: name)
ref.child("families").queryOrderedByKey().queryEqualToValue(familyID).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
for child in snapshot.children {
if let name = child.value!["name"] as? String {
self.family = Family(uid: familyID, name: name)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let tabVC = storyBoard.instantiateViewControllerWithIdentifier("Home") as? TabBarViewController
tabVC?.user = self.user
tabVC?.family = self.family
self.window?.rootViewController = tabVC
}
}
})
}
}
})
}
TabBarController:
var user: User?
var family: Family?
override func viewDidLoad() {
super.viewDidLoad()
print(user?.name)
print(family?.name)
let navVC = self.viewControllers![0] as? UINavigationController
let itemsNav = self.viewControllers![1] as? UINavigationController
let leaderNav = self.viewControllers![2] as? UINavigationController
let choresVC = navVC!.topViewController as? ChoresViewController
let itemsVC = itemsNav!.topViewController as? ShoppingListViewController
let leaderVC = leaderNav!.topViewController as? LeaderBoardViewController
choresVC?.user = self.user
choresVC?.family = self.family
itemsVC!.user = self.user
itemsVC!.family = self.family
leaderVC!.user = self.user
leaderVC!.family = self.family
}
The code I have still isn't great but it has solved the problem. Hope it helps some of you out.