Tap Push Notifications : can't be directed to specific ViewController - ios

I'm working on app that includes a messenger feature ,the problem is every time i tap on the push notification im directed to the app itself rather than the message itself, i believe the code is correct, might it be a matter of swift version ....?
// AppDelegate
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
let gcmMessageIDKey = "gcm.message_id"
if let messageID = userInfo[gcmMessageIDKey] {
print("messageID: \(messageID)")
}
connectToFirebase()
Messaging.messaging().appDidReceiveMessage(userInfo)
if let dictString = userInfo["gcm.notification.customData"] as? String {
print("dictString \(dictString)")
if let dict = convertToDictionary(text: dictString) {
if let uid = dict["userId"] as? String,
let fullname = dict["username"] as? String,
let email = dict["email"] as? String,
let profileImageUrl = dict["profileImageurl"] as? String {
let user = User(uid: uid, fullname: fullname, email: email, profileImageurl: profileImageUrl, status: "")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let chatVC = storyboard.instantiateViewController(withIdentifier: IDENTIFIER_CHAT) as! ChatViewController
chatVC.partnerUserName = user.fullname
chatVC.partnerId = user.uid
chatVC.partnerUser = user
guard let currentVC = UIApplication.topViewController() else {
return
}
currentVC.navigationController?.pushViewController(chatVC, animated: true)
}
}
}
Extentions
extension UIApplication {
class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topViewController(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topViewController(controller: presented)
}
return controller
}
}

Related

How to load viewController when user tap on notification in iOS Swift?

I have done push notification using FCM on the app side. When the user taps on the notification it navigates to specific viewController from the app side to custom SDK. I have tried many ways but viewController is not showing but all functionalities are loaded successfully.
1. First attempt: [Notification tap is detected and passed data from the app side to framework. Loaded particular viewController functionalities but viewController are not showing.]
When user tap notification from the app side, it will send data to the framework to show a particular viewController.
here is the code for the app side:
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
if(application.applicationState == .active){
print("user tapped the notification bar when the app is in foreground")
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print("didReceive notification tapped",userInfo)
TaskName = userInfo[taskName] as? String ?? ""
print("TaskName::::", TaskName ?? "")
ProcessInstanceId = userInfo[processInstanceId] as? String ?? ""
print("ProcessInstanceId::::", ProcessInstanceId ?? "")
processDefinitionName = userInfo[ProcessDefinitionId] as? String ?? ""
print("processDefinitionName::::", processDefinitionName ?? "")
TaskID = userInfo[taskId] as? String ?? ""
print("taskID::::", TaskID ?? "")
FormKey = userInfo[formKey] as? String ?? ""
print("FormKey::::", FormKey ?? "")
Types = userInfo[type] as? String ?? ""
print("Type::::", Types ?? "")
Title = userInfo[title] as? String ?? ""
print("Title::::", Title ?? "")
Body = userInfo[body] as? String ?? ""
print("Body::::", Body ?? "")
CreatedDate = userInfo[created] as? String ?? ""
print("created:::", CreatedDate ?? "")
AFlowBuilder(self).callFormView(taskName: TaskName ?? "", processInstanceID: ProcessInstanceId ?? "", ProcessDefinitionName: processDefinitionName ?? "", taskId: TaskID ?? "", formKey: FormKey ?? "", title: Title ?? "", type: Types ?? "", body: Body ?? "", created: CreatedDate ?? "", formStatus: false)
}
completionHandler()
}
Here is the code from the framework side:
private var taskViewNew: UIViewController?
public func callFormView(taskName: String, processInstanceID: String, ProcessDefinitionName: String, taskId: String, formKey: String, title: String, type: String, body: String, created: String, formStatus: Bool){
let newNotification = makeSaveNotification(taskName: taskName, processInstanceID: processInstanceID, ProcessDefinitionName: ProcessDefinitionName, taskId: taskId, formKey: formKey, title: title, type: type, body: body, created: created, formStatus: formStatus)
let realm = try! Realm()
// let realmData = realm.objects(NotificationRealmModel.self).filter("name = \(userNameRealm ?? "")").first!
try! realm.write {
realm.add(newNotification)
print("ream notification saved path url:: call form view", realm.configuration.fileURL ?? "")
}
let controller = CreateCardViewController()
let str = formKey
let result = String(str.dropFirst(7))
print(result)
let s = String(result.dropLast(10))
print("newFormKey call form view", s )
let v = convap(text: s)
controller.processInstanceId = processInstanceID
controller.cardName = ""
controller.TaskIdValue = taskId
controller.formKey = v
controller.tabName = "NotificationTapped"
controller.fullFormKey = formKey
self.taskViewNew?.addChild(controller)
self.taskViewNew?.view.addSubview(controller.view)
controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// controller.didMove(toParent: taskViewNew)
taskViewNew?.present(controller, animated: true, completion: nil)
}
Second attempt: [Notification detected in the app side and passed value to viewController. And, Inside viewController framework method is called to load framework viewController but all functionality is loaded successfully but the view is not loaded]
Here is the code from the app side:
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
if(application.applicationState == .active){
print("user tapped the notification bar when the app is in foreground")
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print("didReceive notification tapped",userInfo)
TaskName = userInfo[taskName] as? String ?? ""
print("TaskName::::", TaskName ?? "")
ProcessInstanceId = userInfo[processInstanceId] as? String ?? ""
print("ProcessInstanceId::::", ProcessInstanceId ?? "")
processDefinitionName = userInfo[ProcessDefinitionId] as? String ?? ""
print("processDefinitionName::::", processDefinitionName ?? "")
TaskID = userInfo[taskId] as? String ?? ""
print("taskID::::", TaskID ?? "")
FormKey = userInfo[formKey] as? String ?? ""
print("FormKey::::", FormKey ?? "")
Types = userInfo[type] as? String ?? ""
print("Type::::", Types ?? "")
Title = userInfo[title] as? String ?? ""
print("Title::::", Title ?? "")
Body = userInfo[body] as? String ?? ""
print("Body::::", Body ?? "")
CreatedDate = userInfo[created] as? String ?? ""
print("created:::", CreatedDate ?? "")
}
window = UIWindow(frame: UIScreen.main.bounds)
let homeViewController = ViewController()
homeViewController.Body = Body
homeViewController.CreatedDate = CreatedDate
homeViewController.FormKey = FormKey
homeViewController.processDefinitionName = processDefinitionName
homeViewController.ProcessInstanceId = ProcessInstanceId
homeViewController.TaskID = TaskID
homeViewController.Title = Title
homeViewController.Types = Types
homeViewController.view.backgroundColor = UIColor.red
window!.rootViewController = homeViewController
window!.makeKeyAndVisible()
completionHandler()
}
Here is the code viewController from the app side, it will load the framework viewController method.
Attempt 1:
override func viewDidAppear(_ animated: Bool) {
let controller = CreateCardViewController()
let str = FormKey
let result = String(str?.dropFirst(7) ?? "")
print(result)
let s = String(result.dropLast(10))
print("newFormKey call form view", s )
let v = convap(text: s)
controller.processInstanceId = ProcessInstanceId
controller.cardName = ""
controller.TaskIdValue = TaskID
controller.formKey = v
controller.tabName = "NotificationTapped"
print(controller.tabName)
controller.fullFormKey = FormKey
add(asChildViewController: controller)
}
private func add(asChildViewController viewController: UIViewController) {
// Add Child View Controller
addChild(viewController)
// Add Child View as Subview
view.addSubview(viewController.view)
// Configure Child View
viewController.view.frame = view.bounds
viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// Notify Child View Controller
viewController.didMove(toParent: self)
}
Attempt: 2
override func viewDidAppear(_ animated: Bool) {
print("Presenting next...")
let controller = CreateCardViewController()
let str = FormKey
let result = String(str?.dropFirst(7) ?? "")
print(result)
let s = String(result.dropLast(10))
print("newFormKey call form view", s )
let v = convap(text: s)
controller.processInstanceId = ProcessInstanceId
controller.cardName = ""
controller.TaskIdValue = TaskID
controller.formKey = v
controller.tabName = "NotificationTapped"
print(controller.tabName)
controller.fullFormKey = FormKey
present(controller, animated: true, completion: nil)
}
Any help much appreciated pls...
I have such task currently maybe it is a little bit simpler but this is my code:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
if let navigationController = window?.rootViewController as? UINavigationController {
navigationController.popToRootViewController(animated: false)
if let someViewController = navigationController.storyboard?.instantiateViewController(withIdentifier: "SomeViewController") as? SomeViewController {
navigationController.pushViewController(someViewController, animated: true)
}
}
}
In my case, it works fine because I have UINavigationController as a root of my app, and I manage my navigation through it. This is important to be sure what you have on your stack of views right now and how to clear it.
Also, you can see that I use this line for instantiating my new ViewController
if let someViewController = navigationController.storyboard?.instantiateViewController(withIdentifier: "SomeViewController") as? SomeViewController
But this is not important, just be sure that your ViewController is correctly initiated.
Good luck.
I used the top view controller to present the desired view.
To fetch top view controller:
func topController() -> UIViewController {
if var topController = UIApplication.shared.keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
return topController
}
return (UIApplication.shared.keyWindow?.rootViewController)!
}
Then on receiving notification:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print(userInfo)
guard Utility.shared.userInfo != nil else { return }
let vc : EventDetailVC = EVENTSSTORYBOARD.viewController(id: "EventDetailVC") as! EventDetailVC
vc.eventID = event_id
vc.eventType = EventType.Invite
let nav = UINavigationController(rootViewController: vc)
nav.modalPresentationStyle = .fullScreen
self.topController().present(nav, animated: true, completion: nil)
}
Let me know if it works for you.
Use NotificationCenter create a custom NSNotification.Name and subscribe your viewcontroller to the created notification name using
NotificationCenter.default.addObserver(self, selector: #selector(openView), name: <<custom notification name>>, object: nil)
after that using the selector function you can pass all the parameters to the view controller
#objc func openView(notification: Notification){}
and in didFinishLaunchingWithOptions post to the above custom notification using this
let userInfo = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification]
if (userInfo != nil){
DispatchQueue.main.asyncAfter(deadline: .now() + 0.9) {
NotificationCenter.default.post(name: <<custom notification name>>, object: nil, userInfo: userInfo as! [AnyHashable : Any]?)
}
}
if you have multiple viewcontrollers that needs to be open you can create a base view controller class and put above code in the base class and extend the viewcontrollers by the base class

In iOS 11.3 didReceiveNotification function not calling on tap

In iOS 11.3 and above version Mobiles didReceiveNotification function not calling after clicking on notifications. Its working Properly in iOS 9.3 versions.
In my application i wanted to open a different view controller on tap of the application. Based on the notification type.
I am getting the notification its inserting into data base. But after clicking on notification instead of opening required view controller its opening app main screen only.
But in iOS 9 all functionalities are working fine.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
let aps = userInfo[AnyHashable("gcm.notification.m")]
if application.applicationState != .inactive{
if(aps != nil){
print(aps)
self.insertNotification(data: "\(aps)")
}
}
if application.applicationState == .active {
}
else if application.applicationState == .background{
}
else if application.applicationState == .inactive{
let array: [Any] = ["\(aps)"]
self.ns.set(array, forKey: "notify")
var notification:String = "\(aps)"
if let range = notification.range(of: "Optional") {
notification.removeSubrange(range)
}
notification = String(notification.dropLast())
notification = String(notification.dropFirst())
let json:String = "\(notification)"
let encodedString : NSData = (json as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData
do {
var finalJSON = try JSON(data: encodedString as Data)
var activityName:String!
var url:String!
var serviceUrl = LMUrl()
if(finalJSON["Notify_Click"].dictionary != nil){
activityName = finalJSON["Notify_Click"]["activity_name"].string!
url = finalJSON["Notify_Click"]["url"].string!
if(activityName == "BuyLeads"){
let calWebURL: [String] = ["Buy Leads",serviceUrl.buyLeads+"\(url)&"]
ns.set(calWebURL, forKey: "web2")
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController:webViewController = mainStoryboard.instantiateViewController(withIdentifier: "WebView") as! webViewController
let navi = UINavigationController.init(rootViewController: initialViewController)
self.window?.rootViewController = navi
self.window?.makeKeyAndVisible()
}
else if(activityName == "RC"){
let calWebURL: [String] = ["Report Conversion",serviceUrl.reportConversion+"\(url)&"]
print(calWebURL)
ns.set(calWebURL, forKey: "web")
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController:webViewController = mainStoryboard.instantiateViewController(withIdentifier: "WebView") as! webViewController
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
else{
print("no Action")
}
}else{
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController:notificationsViewController = mainStoryboard.instantiateViewController(withIdentifier: "notificationViewController") as! notificationsViewController
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
}catch{
}
}
else{
print("Notification")
}
completionHandler(.newData)
}
func insertNotification(data:String!){
let FMDBInfo:Tbl_Info3 = Tbl_Info3()
let dateFormatter : DateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = Date()
let timestamp = dateFormatter.string(from: date)
let time = DateFormatter.localizedString(from: NSDate() as Date, dateStyle: .medium, timeStyle: .short)
//print(timestamp)
FMDBInfo.notification = data as! String
FMDBInfo.time = timestamp
FMDBInfo.time2 = time
print(FMDBInfo)
let isInserted = FMDBDatabaseModel.getInstance().NotificationInsertData(FMDBInfo)
if isInserted{
print("Inserted")
}else{
print("Error while inserting data")
}
}

swift ios how to access AnyHashable data in swift

How to access any AnyHashable data in swift i have my data below , below is the log when i click the notification . When i click notif and when the data logs i want to print or get it so that i can load it on the view . it is already working and it log when i click the notif what i want is how to get it to load in the view.
what i have done
guard
let aps = userInfo[AnyHashable("aps")] as? NSDictionary,
let alert = aps["alert"] as? NSDictionary,
let body = alert["body"] as? String,
let title = alert["title"] as? String
else {
return
}
print("Title: \(title) \nBody:\(body)")
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
data
[AnyHashable("aps"): {
alert = {
body = "yuuu - 5.00";
title = "New Chore!";
};
"content-available" = 1;
}, AnyHashable("data"): {
chore = {
desc = huu;
name = yuuu;
pk = 125;
reward = "5.00";
sched = "2018-04-12T09:52:13+08:00";
};
"notification_id" = 16;
pusher = {
publishId = "pubid-01ff965a-20af-4a58-9901-89782043d832";
};
}]
You can Possibly Try:
Update for Swift 5+:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
guard let arrAPS = userInfo["aps"] as? [String: Any] else { return }
if application.applicationState == .active{
guard let arrAlert = arrAPS["alert"] as? [String:Any] else { return }
let strTitle:String = arrAlert["title"] as? String ?? ""
let strBody:String = arrAlert["body"] as? String ?? ""
let alert = UIAlertController(title: strTitle, message: strBody, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default) { action in
print("OK Action")
})
self.window?.rootViewController?.present(alert, animated: true)
} else {
guard let arrNotification = arrAPS["notification"] as? [String:Any] else { return }
guard let arrAlert = arrNotification["alert"] as? [String:Any] else { return }
let strTitle:String = arrAlert["title"] as? String ?? ""
print("Title --", strTitle)
let strBody:String = arrAlert["body"] as? String ?? ""
print("Body --", strBody)
}
}
Swift 2+ :
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
guard let dictAPS = userInfo["aps"] as? NSDictionary else { return }
if application.applicationState == .active{
let title = dictAPS.value(forKeyPath: "alert.title")
let body = dictAPS.value(forKeyPath: "alert.body")
let alert = UIAlertController(title: "\(title!)", message: "\(String(describing: body))", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default) { action in
})
self.window?.rootViewController?.present(alert, animated: true)
}else{
guard let dictNoti = dictAPS.value(forKey: "notification") as? NSDictionary else { return }
let title = dictNoti.value(forKeyPath: "alert.title")
print(title)
let body = dictNoti.value(forKeyPath: "alert.body")
print(body)
}
}
anwer : on how to load notif data when notif is tap
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo["gcmMessageIDKey"] {
print("Message ID: \(messageID)")
}
switch response.actionIdentifier {
case "action1":
print("Action First Tapped")
case "action2":
print("Action Second Tapped")
default:
break
}
// Print full message.
print(userInfo)
Messaging.messaging().appDidReceiveMessage(userInfo)
completionHandler()
}
APS data can be checked as below. You can check each keys as below to avoid crashing app if particular key is not available in notification data and handle accordingly.
if (userInfo["aps"] as? [String:Any]) != nil {
if let data = userInfo["data"] as? String{
if let desc = userInfo["desc"] as? String {
//Access variable desc here...
print(desc)
}
}
}

Ios10 swift 3 core spotlight search cant get title of nsuseractivity

im not getting anything on userActivity.title , it turns nil at appdelegate. check below, this used to work in ios9 , that i can remember. i need to get the Title set in attributeSet.title , but it is always nil.
Code to index my item
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)
attributeSet.title = "ALFRESCO" //restnombre //project[0]
attributeSet.contentDescription = "\(tipocomida)"
let item = CSSearchableItem(uniqueIdentifier: "\(restid)", domainIdentifier: "com.cgcompany.restaurants", attributeSet: attributeSet)
CSSearchableIndex.default().indexSearchableItems([item]) { (error: Error?) -> Void in
if let error = error {
print("Indexing error: \(error.localizedDescription)")
} else {
print("Search item successfully indexed!")
}
}
Code in app delegate
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {
// if #available(iOS 9.0, *) {
print("CALLING CONTINUE USER ACT")
if userActivity.activityType == CSSearchableItemActionType {
print("ACT TYPE IS CSSEARCHABLEITEM")
var title = "NOTITLE"
if (userActivity.title) != nil {
title = userActivity.title!
}
if let uniqueIdentifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String {
print ("Calling FROM SPOTLIGHTSEARCH")
let rootViewController = self.window!.rootViewController as! UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let restaurantdetail = mainStoryboard.instantiateViewController(withIdentifier: "restaurant_detail2") as! VCviendorest
let detailurl = "http://www.urltoget.com/iphone/\(uniqueIdentifier)/fromiOSSearch.html"
restaurantdetail.IDREST = uniqueIdentifier
restaurantdetail.NOMBRERESTAURANT = "\(title)" //userActivity.title!
restaurantdetail.DETAILURL = detailurl
rootViewController.pushViewController(restaurantdetail, animated: true)
}
}
// } else {
// Fallback on earlier versions
// }
return true
}
I had the same problem as yours when my app run on iOS 10 device (on XCode 7.1), after couple tests, I need to combine the NSUserActivity with CSSearchableItemAttributeSet, and stop using CSSearchableItem and indexSearchableItems method of CSSearchableIndex. Here's the code:
// Config the attributeSet
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)
attributeSet.title = "ALFRESCO" //restnombre //project[0]
attributeSet.contentDescription = "\(tipocomida)"
attributeSet.identifier = "\(restid)"
if #available(iOS 10, *) {
// Init user activity combining with the attribute set
let bundleId = NSBundle.mainBundle().bundleIdentifier ?? ""
let activity = NSUserActivity(activityType: "\(bundleId).spotlight")
activity.userInfo = [CSSearchableItemActivityIdentifier: attributeSet.identifier!]
activity.title = attributeSet.title
activity.eligibleForHandoff = false
activity.eligibleForSearch = true
activity.eligibleForPublicIndexing = true
activity.contentAttributeSet = attributeSet
activity.becomeCurrent()
} else {
// continue using CSSearchableItem with your old code
// let item = CSSearchableItem(...
}
On your app delegate, you need to update the check to:
let activityType = (NSBundle.mainBundle().bundleIdentifier ?? "") + ".spotlight"
if userActivity.activityType == CSSearchableItemActionType || userActivity.activityType == activityType {
// here for your code
}

Downloading firebase data in the app delegate

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.

Resources