How to call viewcontroller method from AppDelegate if I use TabBar Navigation - swift

I really need a help with calling view controller method as soon as my app open when the remote notification comes in especially when using TabBar navigation.When I open my app when the notification arrive,it will call didReceiveRemoteNotification because I enabled "content-available = 1".But,the problem is I don't know how to access my HomeViewController method refresh() because I use TabBar Navigation.I need to call HomeViewController refresh() method inside didReceiveRemoteNotification because it really need to refresh the data from core and the notification that arrived are saved at coredata.
Everytime the notification comes in,I save them at realm database and show user at HomeViewController
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
if let aps = userInfo["aps"] as? NSDictionary{
if let alert = aps["alert"] as? NSDictionary{
if let mbody = alert["body"] as? String{
print("Message Body : \(body)")
body = mbody
}
if let mtitle = alert["title"] as? String{
print("Message Title : \(title)")
title = mtitle
}
}
}
let newNotification = NotificationList()
newNotification.title = title
newNotification.body = body
//Realm insert query
oneSignalHelper.insertOneSignalNotification(newNotification)
print("Remote Receive")
//This condition isn't working
if let viewController = self.window?.rootViewController as? HomeViewController {
print("Remote Receive Read")
//This method is HomeViewController method which I gonna use for refresh when I tapped notification.It read that are save in realm database and show results.
viewController.readNotificationsAndUpdateUI()
}
handler(UIBackgroundFetchResult.NewData)
}
This is readNotificationsAndUpdateUI() from HomeViewController
func readNotificationsAndUpdateUI(){
notifications = realm.objects(NotificationList)
self.notificationTableView.setEditing(false, animated: true)
self.notificationTableView.reloadData()
self.refreshControl?.endRefreshing()
}

I suggest you using NSNotificationCenter, just post notification inside didReceiveRemoteNotification like this:
NSNotificationCenter.defaultCenter().postNotificationName("refreshNotification", object: nil)
In your HomeViewController in viewDidLoad() you should subscribe to the notification center like this:
NSNotificationCenter.defaultCenter().addObserver( self, selector: "refresh", name: "refreshNotification", object: nil)

Not sure if it helps but I solved it this way, based on previous answer
Load Storyboard
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
Load ViewController (check that you have an identifier in your storyboard for this ViewController!)
let bestellvorschlag = storyBoard.instantiateViewController(identifier: "Bestellvorschlag") as! Bestellvorschlag
Load Function on ViewController
bestellvorschlag.loaddata() //Loads CoreData into Array of artikels
Maybe Modify the Tabbar Badge with the number of Results
let tabbarcontroller = self.window?.rootViewController as! UITabBarController
if bestellvorschlag.artikels.count > 0
{
if let tabItems = tabbarcontroller.tabBar.items {
// Third Tab!
let tabItem = tabItems[2]
tabItem.badgeValue = bestellvorschlag.artikels.count.description
}
}
Complete Function in appDelegate
func applicationDidBecomeActive(_ application: UIApplication) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let bestellvorschlag = storyBoard.instantiateViewController(identifier: "Bestellvorschlag") as! Bestellvorschlag
bestellvorschlag.loaddata()
let tabbarcontroller = self.window?.rootViewController as! UITabBarController
if bestellvorschlag.artikels.count > 0
{
if let tabItems = tabbarcontroller.tabBar.items {
// Third Tab!
let tabItem = tabItems[2]
tabItem.badgeValue = bestellvorschlag.artikels.count.description
}
}
}

Related

How To Move To Spesific Screen iOS When User Tap Notification FCM

I made a notification, now my notification has appeared on iOS when I tap the notifications bagde the notification appears I want to switch to another View Controller page.
This my code in AppDelegate.swfit
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print("user data msg \(userInfo)")
guard let aps = userInfo["aps"] as? [String : AnyObject] else {
print("Error parsing aps")
return
}
print(aps)
if let alert = aps["alert"] as? String {
body = alert
} else if let alert = aps["alert"] as? [String : String] {
body = alert["body"]!
title = alert["title"]!
}
if let alert1 = aps["category"] as? String {
msgURL = alert1
}
print("Body\(body)")
print(title)
print(msgURL)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "register")
vc.modalPresentationStyle = .overFullScreen
present(vc, animated: true)
}
}
But I got error: Cannot find 'present' in scope Where I should put my code for naviagtion when the user got a notification in Swift.
present() is a method on UIViewController, so you'll have to have a reference to a view controller that you can call that method on.
This can vary by the structure of your app -- especially if you're using a SceneDelegate, you have multiple windows, etc.
My suggestion is that you post a Notification that you can listen for in whatever has a reference to your top view controller. For example, instead of where you have present, you could do something like this:
let dataDict : [String : UIViewController] = ["vc": vc]
NotificationCenter.default.post(name: Notification.Name("ShowVC"), object: nil, userInfo: dataDict)
Then, assuming you're using a SceneDelegate, you could do this in your scene(_ scene: UIScene, willConnectTo) function:
NotificationCenter.default.publisher(for: Notification.Name("ShowVC"))
.compactMap {
$0.userInfo as? [String: UIViewController]
}
.sink {
guard let vc = $0["vc"] else {
return
}
window?.rootViewController?.present(vc, animated: true)
}.store(in: &cancelSet)
At the top of your file you'll need to import Combine and then your SceneDelegate will need a new property in order for the above code to work:
var cancelSet: Set<AnyCancellable> = []
Even if you aren't using a SceneDelegate, the basic concepts here should apply to other scenarios.
Note, however, that this is not a foolproof plan -- the root view controller has to be the visible view in order for this to work. This all may depend on your architecture. Search SO for "topmost view controller" to see plenty of discussion on this topic.

Swift segue not doing what it is supposed to do

I am having a little problem with a segue in my application.
When I try to push a segue so that it has a navbar it shows up correctly in the storyboard but not when I try it on my iPhone.
This is an overview of a couple of view controllers where my problem lays.
This is supposed to be the segue, so you can see that it has a navigation bar and is correctly positioned on the storyboard.
This is the view on the iPhone. No navigation bar or nothing. I tried everything but can't seem to find a solution to this problem.
Does anyone what the problem could be?
A little extra side information:
I don't know if may have something to do with the problem but the navigation view controller is not always present only when the user is logged in the app. this is decided on a log in screen if the user is not logged in the user will see a normal login screen. Else it will go to navigation view controller with a view did appear function and self.present.
Here is the code that handles that action.
// Sees if the user is logged, If yes --> go to the account detail page else go to the account view.
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let data = UserDefaults.standard.data(forKey: "User") {
do {
// Create JSON Decoder
let decoder = JSONDecoder()
// Decode Note
_ = try decoder.decode(User.self, from: data)
guard let loginVC = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier:
"AccountDetailViewController") as? AccountDetailViewController else { return }
loginVC.modalPresentationStyle = .overCurrentContext
self.present(loginVC, animated: false, completion: {})
} catch {
print("Unable to Decode Note (\(error))")
}
}
}
You should push view controller instead of present. Please check this article to know more about Pushing, Popping, Presenting, & Dismissing ViewControllers
You can push AccountDetailViewController without segues. And you don't need to call performSegue(withIdentifier:) into tableView's didSelect function.
Remove segue from Interface Builder
let navigator = UINavigationController()
guard let loginVC = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier:
"AccountDetailViewController") as? AccountDetailViewController else { return }
loginVC.modalPresentationStyle = .overCurrentContext
navigator.pushViewController(loginVC, animated: true)
After succesful login, you are presenting AccountDetailViewController without adding it in a navigation controller. I would suggest you to use these extensions that i created.
extension UIViewController {
func pushVC(vcName : String) {
let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: vcName)
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
func pushVC(storyboardName : String, vcName : String) {
let vc = UIStoryboard.init(name: storyboardName, bundle: Bundle.main).instantiateViewController(withIdentifier: vcName)
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
func popVC() {
self.navigationController?.popViewController(animated: true)
}
func makeRootVC(storyBoardName : String, vcName : String) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let vc = UIStoryboard(name: storyBoardName, bundle: Bundle.main).instantiateViewController(withIdentifier: vcName)
let nav = UINavigationController(rootViewController: vc)
nav.navigationBar.isHidden = true
appDelegate.window?.rootViewController = nav // If using XCode 11 and above, copy var window : UIWindow? in your appDelegate file
let options: UIView.AnimationOptions = .transitionCrossDissolve
let duration: TimeInterval = 0.6
UIView.transition(with: appDelegate.window!, duration: duration, options: options, animations: {}, completion: nil)
}
}
Now in your case, when a user logs in, you should change your root view controller to AccountDetailViewController. So first, copy paste the above extension anywhere in your file and then use it like this:
// Sees if the user is logged, If yes --> go to the account detail page else go to the account view.
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let data = UserDefaults.standard.data(forKey: "User") {
do {
// Create JSON Decoder
let decoder = JSONDecoder()
// Decode Note
_ = try decoder.decode(User.self, from: data)
self.makeRootVC(storyBoardName : "Main", vcName :"AccountDetailViewController")
} catch {
print("Unable to Decode Note (\(error))")
}
}
}

Whose view is not in the window hierarchy only in First Launch

I have an Onboarding screen that I'm showing to the new users when they first open the app.
In my appDelegate I check whether is the first launch or not.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var initialViewController = storyboard.instantiateViewController(withIdentifier: "OnBoarding")
let userDefaults = UserDefaults.standard
if userDefaults.bool(forKey: "onBoardingComplete") {
initialViewController = storyboard.instantiateViewController(withIdentifier: "MainApp")
}
window?.rootViewController = initialViewController
window?.makeKeyAndVisible()
}
Also I have a collectionViewCell that I have some buttons and when I click them I get an Alert with informations.
Example of one button
#IBAction func guide3Btn(_ sender: Any) {
let infoVC = infoService.info(title: "Title", body: "Information")
self.window?.rootViewController?.present(infoVC, animated: true, completion: nil)
}
When the user first launches the app if he clicks the info button gets this:
Warning: Attempt to present <MyApp.InfoViewController: 0x7f91db45cfb0> on <MyApp.OnbBoardViewController: 0x7f91db506af0> whose view is not in the window hierarchy!
If the user reopens the app everything is ok. I know that when we have first launch we have onBoarding as root controller but I can't understand how to fix this.
Update
This is the infoService class. I use a new storyboard to create the alert.
class InfoService {
func info(title: String, body: String) -> InfoViewController {
let storyboard = UIStoryboard(name: "InfoStoryboard", bundle: .main)
let infoVC = storyboard.instantiateViewController(withIdentifier: "InfoVC") as! InfoViewController
infoVC.infoBody = body
infoVC.infoTitle = title
return infoVC
}
}
You can try add your storyboard instantiate code blocks to main thread using DispatchQueue.main.async like below:
I solved almost all of my whose view is not in the window hierarchy! problems.
DispatchQueue.main.async {
let infoVC = storyboard.instantiateViewController(withIdentifier: "InfoVC") as! InfoViewController
infoVC.infoBody = body
infoVC.infoTitle = title
}
return infoVC
Referenced from : https://stackoverflow.com/a/45126338/4442254

How to set a new root view controller

I wonder if its possible to set a new root VC?
My app gets init with a uinavigation controller that has a table view to be the root VC.
Then from the table view I am running another segue to a login window (present modally) If you then login you end up in the red VC/account page. What I want to do now is to set the red VC to be the new root VC of the app, and remove all underlying VC's. So that I can show a menu button/icon instead of a "Back" button
I have found this but I dont understand how to use it:
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let yourViewController: ViewController = storyboard.instantiateViewControllerWithIdentifier("respectiveIdentifier") as! ViewController
let navigationController = self.window?.rootViewController as! UINavigationController
navigationController.setViewControllers([yourViewController], animated: true)
But I cannot get it to work. So is it possible to make the red vc in the picture act as the new root VC.
Swift 4.2
May be you should try this
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let redViewController = mainStoryBoard.instantiateViewController(withIdentifier: "respectiveIdentifier") as! ViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = redViewController
Swift 4, 5, 5.1
let story = UIStoryboard(name: "Main", bundle:nil)
let vc = story.instantiateViewController(withIdentifier: "NewViewController") as! NewViewController
UIApplication.shared.windows.first?.rootViewController = vc
UIApplication.shared.windows.first?.makeKeyAndVisible()
Swift 3 Update:-
let testController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "testController") as! TestController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = testController
Swift 4 Answer
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
let navigationController = UINavigationController(rootViewController: nextViewController)
let appdelegate = UIApplication.shared.delegate as! AppDelegate
appdelegate.window!.rootViewController = navigationController
UINavigationController has a viewControllers property, which is a NSArray, And you can replaced it with your own NSArray of view controllrs.
This can be done as show in below sample code.
let newViewController = self.storyboard?.instantiateViewControllerWithIdentifier("YourViewControllerollerID") as! YourViewController
let customViewControllersArray : NSArray = [newViewController]
navigationController?.viewControllers = customViewControllersArray as! [UIViewController]
And if you want to show this new root view controller you can just call UINavigationController's popToRootViewController() method.
navigationController?.popToRootViewControllerAnimated(true)
In order to get the code snippet from the original question to work, I had to make a change to the third line
let navigationController = self.navigationController!
I am using this code in an #IBAction in the view controller that precedes the new root view controller.
Using the original code, I was receiving an error saying that my view controller had no member called window. After looking at the documentation, I could find no property named window. I'm wondering if the original block of code above was intended to be used inside a UINavigationController file.
Here is the block in its entirety.
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let todayViewController: TodaysFrequencyViewController = storyboard.instantiateViewControllerWithIdentifier("todaysFrequency") as! TodaysFrequencyViewController
let navigationController = self.navigationController!
navigationController.setViewControllers([todayViewControl ler], animated: true)
I wonder if its possible to set a new root VC?
Yes, it's possible. How you do it depends on the context...
My app gets init with a uinavigation controller that has a table view to be the root VC.
There are actually two things that are commonly called the "root view controller":
UIWindow has a rootViewController property, which is writeable.
UINavigationController has no rootViewController property, but it does have an initializer called -initWithRootViewController:. You can set the nav controller's "root" view controller by setting it's viewControllers property.
It sounds like you're trying to change the window's root view controller, but the code you show only changes the nav controller's viewControllers property. Try setting the window's rootViewController property directly. Understand, however, that if you take that approach then the navigation controller will go away too. If you want to keep the nav controller, on the other hand, go with your current approach.
But I cannot get it to work. So is it possible to make the red vc in the picture act as the new root VC.
More information here would be helpful. What do you mean by "cannot get it to work"? What happens, and what do you expect to happen?
For swift 4.0.
In your AppDelegate.swift file in didfinishedlaunchingWithOptions method, put the following code.
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let rootVC = MainViewController() // your custom viewController. You can instantiate using nib too. UIViewController(nib name, bundle)
let navController = UINavigationController(rootViewController: rootVC) // Integrate navigation controller programmatically if you want
window?.rootViewController = navController
return true
}
Hope it will work just fine.
For Swift 5 Users you can do this way and this will definitely work for you.
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
manageLoginSession()
guard let _ = (scene as? UIWindowScene) else { return }
}
func manageLoginSession() {
guard let window = window else {return}
if UserDefaults.standard.bool(forKey: "_key_AlreadyLogin") == true {
window.rootViewController = UIStoryboard(name: "Dashboard", bundle: nil).instantiateInitialViewController()
}else{
window.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
}
}
You can use this code when you click the login button :-
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var vc = mainStoryboard.instantiateViewControllerWithIdentifier("respectiveIdentifier") as ViewController
UIApplication.sharedApplication().keyWindow.rootViewController = vc
How and from where are you presenting redVC?
You could make it root view controller of your UINavigationController, so you would still have ability to push and pop view controllers.
self.navigationController?.viewControllers = [self];
You can use this bit of code:
let newViewController = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
let customViewControllersArray : NSArray = [newViewController]
self.navigationController?.viewControllers = customViewControllersArray as! [UIViewController]
self.navigationController?.pushViewController(newViewController, animated: true)
If you need to set rootViewController with some animations, here is the code:
guard let window = UIApplication.shared.keyWindow else {
return
}
guard let rootViewController = window.rootViewController else {
return
}
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MainTabbar")
vc.view.frame = rootViewController.view.frame
vc.view.layoutIfNeeded()
UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
window.rootViewController = vc
}, completion: { completed in
// maybe do something here
})
For Swift 5 and above this may work for you.
if let delegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate {
delegate.window?.rootViewController = newViewController
delegate.window?.makeKeyAndVisible()
}
Swift 4,5
Use this below code for RootViewController
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let mainViewController = storyBoard.instantiateViewController(withIdentifier: "MainViewController") as! MainViewController
let navigationController = UINavigationController(rootViewController: nextViewController)
if let window = UIApplication.shared.delegate?.window {
window?.rootViewController = navigationController
}
once you are in the vc that you want to set as root, just add in your viewDidLoad:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = self
*As per best practice you should check if it is already the root, if not execute the code above.
Swift 3
AppDelegate file:::
#IBAction func btnGoBack(_ sender: UIButton){
self.goToHomeVC()
}
func goToHomeVC(){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier :"HomeVC") as! HomeVC
let navController = UINavigationController.init(rootViewController: viewController)
if let window = self.appDelegate.window, let rootViewController = window.rootViewController {
var currentController = rootViewController
while let presentedController = currentController.presentedViewController {
currentController = presentedController
}
currentController.present(navController, animated: true, completion: nil)
}
}
You can try out this code
func switchRootViewController(rootViewController: UIViewController, animated: Bool, completion: (() -> Void)?) {
guard let window = UIApplication.shared.keyWindow else { return }
if animated {
UIView.transition(with: window, duration: 0.5, options: .transitionCrossDissolve, animations: {
let oldState: Bool = UIView.areAnimationsEnabled
UIView.setAnimationsEnabled(false)
window.rootViewController = rootViewController
UIView.setAnimationsEnabled(oldState)
}, completion: { (finished: Bool) -> () in
if (completion != nil) {
completion!()
}
})
} else {
window.rootViewController = rootViewController
}
}
Any view controller you want to set root just call the below function like
UIApplication.shared.setRootVC(vc)
extension UIApplication {
func setRootVC(_ vc : UIViewController){
self.windows.first?.rootViewController = vc
self.windows.first?.makeKeyAndVisible()
}
}
Just write this and you are good to go.
let sb = UIStoryboard(name: "Main", bundle: nil)
let VC = sb.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
let navRootView = UINavigationController(rootViewController: VC)
self.present(navRootView, animated: true, completion: nil)
This is how you can set the nib as root view controller.
let vc = HomeViewController(nibName: "HomeViewController", bundle: nil)
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = vc
window?.makeKeyAndVisible()
Link to a related question
This answer applies to usage of an existing ViewController from somewhere in the current stack without instantiating and reconfiguring a new controller.
The documentation says: The root view controller provides the content view of the window. Assigning a view controller to this property (either programmatically or using Interface Builder) installs the view controller’s view as the content view of the window. The new content view is configured to track the window size, changing as the window size changes. If the window has an existing view hierarchy, the old views are removed before the new ones are installed.
Just as the documentation says: It removes all views in the stack if the rootViewController is exchanged. No matter what's with the controller. So remove the ViewController from the stack to assure its view won't be removed.
This resulted in my case in the following solution:
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
guard let pageVC = self.onboardingDelegate as? OnboardingPageViewController else { return } // my current stack is in a pageViewController, it also is my delegate
let vc = self // holding myself
pageVC.subViewControllers.removeLast() // removing myself from the list
pageVC.setViewControllers([pageVC.subViewControllers[0]], direction: .forward, animated: false, completion: nil) // remove the current presented VC
appDelegate.window?.rootViewController = vc
vc.onboardingDelegate = nil
appDelegate.window?.makeKeyAndVisible()
}
Swift 4
let storyBoard = UIStoryboard(name: "Your_Storyboard_Name", bundle:Bundle.main)
self.window = UIWindow(frame: UIScreen.main.bounds)
let yourVc = storyBoard.instantiateViewController(withIdentifier: "YourIdentifier") as? YourViewController
if let window = window {
window.rootViewController = yourVc
}
window?.makeKeyAndVisible()
Swift 4,5 and above
If you Use Multiple or single Story board you want to set Different Root view controller of Navigation Controler then I use This Method:
In My case StoryBaord Name is Auth.
func setRootToLogin(transition :CATransition) {
let storyboard = UIStoryboard(name: "Auth", bundle: nil)
let loginNav = storyboard.instantiateViewController(withIdentifier: "AuthNavigationController") as! UINavigationController
window.set(rootViewController: loginNav, withTransition: transition)
let vc = window.rootViewController as! UINavigationController
let loginvc = LoginViewController.instantiateAuth()
vc.setViewControllers([loginvc], animated: true)
}

How do I find the visibleViewController in appdelegate?

I currently instantiate the storyboards programmatically like so:
var iphone35StoryBoard:UIStoryboard = UIStoryboard(name: "iphone35", bundle: nil)
var initialViewController:UIViewController = iphone35StoryBoard.instantiateInitialViewController() as! UIViewController
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
This is my first time working with push notifications, so I'm unsure as the best practice, but what i'm trying to do is in didReceiveRemoteNotification and while the app is in an active state(foreground), I would like to be able to determine what view the user is currently on to determine if i should A) Call a local notificaiton or B) update the view if the push notification corresponds to the visible view.
Using various other SO related questions, I have tried to access the visibleviewcontroller using these variations of code:
let navigationController = application.windows[0].rootViewController as! UINavigationController
1)
let visibleController: AnyObject? = navigationController.visibleViewController
if visibleController is ProfileViewController {
println("this works")
}
and
2)
let viewControllers: [UIViewController] = navigationController.viewControllers as! [UIViewController]
for vc in viewControllers {
if vc is ProfileViewController {
println("this works")
}
}
3)
if let wd = self.window {
var vc = wd.rootViewController
if(vc is UINavigationController){
vc = (vc as UINavigationController).visibleViewController
}
if(vc is ProfileViewController){
println("this works")
}
}
the problem i'm running into is that I can only obtain the rootviewcontroller and never the visible view controller. The rootviewcontroller in this case is a login screen, and despite me being on the profileViewController, i can only obtain the loginviewcontroller. Is this the best method for dealing with push notifications?
Move to destination view controller from storyboard when push notification will came
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main",bundle: nil)
var destViewController : destVC
destViewController = mainStoryboard.instantiateViewControllerWithIdentifier("destVC") as! destVC
var navigationController = UIApplication.sharedApplication().keyWindow!.rootViewController as! UINavigationController
navigationController.pushViewController(destViewController, animated: true)
This is working for me from appdelegate.
Use notification center for more stuff :
NSNotificationCenter.defaultCenter().postNotificationName("name", object: nil, userInfo:nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "method:", name: "name", object: nil)
func method(notification: NSNotification) {
//Do your stuff.
}
Passing data with notification center
NSNotificationCenter.defaultCenter().postNotificationName("name", object:nil, userInfo:["message":"Unable to add \(homeName) Home"])
func method(notification: NSNotification) {
//Do your stuff.
println(notification.userInfo)
}