Navigation Controller becomes nil from todayextension - ios

i have a today extenstion in which there is a button to launch the app,when the app is launched from this button navigation controller becomes nil
i have no idea why this happens ?
this is my code in appdelegate :
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
var storyBoard: UIStoryboard!
var mainViewController: MainViewController!
self.window = UIWindow(frame: UIScreen.main.bounds)
if UserDefaults.getLanguage() == "ar" {
storyBoard = UIStoryboard(name: "MainAR", bundle: nil)
} else {
storyBoard = UIStoryboard(name: "Main", bundle: nil)
}
let viewController = storyBoard.instantiateViewController(withIdentifier: "swRevealController") as! SWRevealViewController
mainViewController = storyBoard.instantiateViewController(withIdentifier: "mainView") as! MainViewController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
viewController.setFront(mainViewController, animated: true)
if url.scheme == "open"
{
switch url.host
{
case "1"?:
mainViewController.isTaxi = true
break
case "2"?:
mainViewController.isPfp = true
break
case "3"?:
mainViewController.isDarbi = true
break
default:
break
}
}
return true
}
please anyone can help ?

This is because of this line that ovewrites the storyboard navigation
self.window?.rootViewController = viewController
you have to embed it inside a navigation like this
self.window?.rootViewController = UINavigationController(rootViewController: viewController)
Edit: before this line init isTaxi
mainViewController.isTaxi = // set it to true / false
viewController.setFront(mainViewController, animated: true)
//
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
var storyBoard: UIStoryboard!
var mainViewController:MainViewController!
self.window = UIWindow(frame: UIScreen.main.bounds)
if UserDefaults.getLanguage() == "ar" {
storyBoard = UIStoryboard(name: "MainAR", bundle: nil)
} else {
storyBoard = UIStoryboard(name: "Main", bundle: nil)
}
mainViewController = storyBoard.instantiateViewController(withIdentifier: "mainView") as! MainViewController
if url.scheme == "open"
{
switch url.host
{
case "1"?:
mainViewController.isTaxi = true
break
case "2"?:
mainViewController.isPfp = true
break
case "3"?:
mainViewController.isDarbi = true
break
default:
break
}
}
let viewController = storyBoard.instantiateViewController(withIdentifier: "swRevealController") as! SWRevealViewController
viewController.setFront(mainViewController, animated: true)
self.window?.rootViewController = UINavigationController(rootViewController: viewController)
self.window?.makeKeyAndVisible()
return true
}

Related

SWRevealViewController side menu is not working in swift 3

I am using SWRevealViewController for side menu functionality. Its working fine but whenever I have added the following code in didFinishLaunchingWithOptions method. side menu is not working for first time launch.
How to solve this problem??
this is my Code :
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// UserDefaults.standard.synchronize()
// IQKeyboardManager.sharedManager().enable = true
self.window = UIWindow(frame: UIScreen.main.bounds)
guard UserDefaults.standard.object(forKey: "IsFirstTime") != nil else {
UserDefaults.standard.set(true, forKey: "IsFirstTime")
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "LaunchViewController") as! LaunchViewController
let navigationController = UINavigationController.init(rootViewController: viewController)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "SWRevealViewController") as! SWRevealViewController
// let navigationController = UINavigationController.init(rootViewController: viewController)
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
return true
}
Thank you
Here you are making LaunchViewController initial VC on first launch. That's why it is not working at first time.
To use SWRevealViewController you need two view controller, one is front view controller which you want to show first time and second is for drawer which maybe tableViewController that contains all other view controller. To add SWRevealViewController call openDrawer() in AppDelegate.
func openDrawer() {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let drawerVC = storyboard.instantiateViewController(withIdentifier: "idDrawerVC") as! RearVC
let dashboardVC = storyboard.instantiateViewController(withIdentifier: "idFrontVC") as! FrontVC
let frontNavigationController = UINavigationController(rootViewController: dashboardVC)
let revealViewController = SWRevealViewController(rearViewController: drawerVC, frontViewController: frontNavigationController)
revealViewController?.delegate = self
revealViewController?.view.backgroundColor = .clear
revealViewController?.modalTransitionStyle = .crossDissolve
window?.rootViewController = revealViewController
}

After login how to set Sidemenu with MainView controller in swift 4

Please, somebody, advise/guide me. How to achieve this task. I am login from my app and after how to set side menu. i have added the code below.
This is Appdeligate code
fileprivate func createMenuView() {
// create viewController code...
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard.instantiateViewController(withIdentifier: "GSMngrMainViewController") as! GSMngrMainViewController
let leftViewController = storyboard.instantiateViewController(withIdentifier: "LeftViewController") as! LeftViewController
let nvc: UINavigationController = UINavigationController(rootViewController: mainViewController)
UINavigationBar.appearance().tintColor = UIColor.black
leftViewController.mainViewController = nvc
let slideMenuController = GSExSlideMenuController(mainViewController:nvc, leftMenuViewController: leftViewController)
slideMenuController.automaticallyAdjustsScrollViewInsets = true
slideMenuController.delegate = mainViewController
self.window?.backgroundColor = UIColor.white
self.window?.rootViewController = slideMenuController
//self.window?.rootViewController = loginViewController
self.window?.makeKeyAndVisible()
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
DropDown.startListeningToKeyboard()
let userId = UserDefaults.standard.string(forKey: "userId")
if userId == nil{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let loginViewController = storyboard.instantiateViewController(withIdentifier: "GSLoginViewController")
let navigationCont = UINavigationController.init(rootViewController: loginViewController)
self.window?.rootViewController = navigationCont
}else{
self.createMenuView()
}
GMSServices.provideAPIKey(googleApiKey)
return true
}
Add this code in the ViewController where you want to have a SideMenu
var customView = Side_Menu_ViewController()
func openSideMenu() {
let controller = storyboard!.instantiateViewControllerWithIdentifier("Side_Menu_ViewController") as! Side_Menu_ViewController
addChildViewController(controller)
controller.view.frame = view.frame
controller.view.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.6)
view.addSubview(controller.view)
controller.didMoveToParentViewController(self)
}
func hideMenu() {
UIView.transitionWithView(self.view, duration: 0.5, options: UIViewAnimationOptions.OverrideInheritedOptions, animations: {
self.customView.view.frame = CGRectMake(self.customView.view.frame.origin.x + 300, 0,self.customView.view.frame.size.width+120,self.view.frame.height);
}, completion: { (finished: Bool) -> () in
})
}
Use two UIViews as shown in the image below - one with black bg and the other with your required things and add the following code in viewDidLoad of SideMenuViewController
SideView.frame = CGRectMake(self.view.frame.width, 0,SideView.frame.size.width,self.view.frame.height)
UIView.transitionWithView(self.view, duration: 0.5, options: UIViewAnimationOptions.OverrideInheritedOptions, animations: {
self.SideView.frame = CGRectMake(self.SideView.frame.origin.x - 210, 0,self.SideView.frame.size.width-130,self.view.frame.size.height);
}, completion: { (finished: Bool) -> () in })

navigation bar disappears when opening view controller via deep link

I've used a tutorial to implement a method in app delegate to open specific view controllers from a HTML button from safari. my app delegate looks like this:
func application(_ app: UIApplication, open URL: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
print("url \(url)")
print("url host :\(url.host!)")
print("url path :\(url.path)")
let urlPath : String = (url.path as String?)!
let urlHost : String = (url.host as String?)!
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if(urlHost != "mywebsite.ir")
{
print("Host is not correct")
return false
}
if(urlPath == "/index"){
let innerPage: ViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController") as! ViewController
self.window?.rootViewController = innerPage
}
self.window?.makeKeyAndVisible()
return true
}
and my HTML button reference is:
open app
but when my app home page opens, the navigation bar is gone and the user gets stuck and doesn't have any access to menu buttons or back button(in case of internal view controllers).
screenshots of home view controller before and after deep link:
Please update your code as below..you should have to put your navigation controller as a window root view controller..
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
print("url \(url)")
print("url host :\(url.host!)")
print("url path :\(url.path)")
let urlPath : String = (url.path as String?)!
let urlHost : String = (url.host as String?)!
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if(urlHost != "mywebsite.ir")
{
print("Host is not correct")
return false
}
if(urlPath == "/index"){
let innerPage: ViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController") as! ViewController
let nav = UINavigationController.init(rootViewController: innerPage)
self.window?.rootViewController = nav
}
self.window?.makeKeyAndVisible()
return true
Does HomeViewController is the initial ViewController? If not, you could call the initial view controller that should be the view controller with a navigation controller.
Try to do this:
mainStoryboard.instantiateInitialViewController()
If the behaviour persists you could embed a NavigationController on code
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController") as! ViewController
let navigationController = UINavigationController(rootViewController: viewController)
self.window?.rootViewController = navigationController
Also you don't need to call window.makeKeyAndVisible()

Why status bar disappear when I tap push notification and move ViewController in swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
/* */
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = UIViewController()
self.window?.windowLevel = UIWindowLevelAlert + 1
self.window?.makeKeyAndVisible()
/*
fetch and add push notification data
*/
goAnotherVC()
}
func goAnotherVC() {
if (application.applicationState == UIApplicationState.active) {
/* active stage is working */
} else if (application.applicationState == UIApplicationState.inactive || application.applicationState == UIApplicationState.background) {
if (type == "1" || type == "2") {
let storyboard: UIStoryboard = UIStoryboard(name: "MyAppointments", bundle: nil)
let apptVC = storyboard.instantiateViewController(withIdentifier: "NotificationDetailViewController") as! NotificationDetailViewController
let navigationController = UINavigationController.init(rootViewController: apptVC)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
} else if (type == "3") {
let storyboard: UIStoryboard = UIStoryboard(name: "MyAppointments", bundle: nil)
let apptVC = storyboard.instantiateViewController(withIdentifier: "NotificationDetailViewController") as! NotificationDetailViewController
let navigationController = UINavigationController.init(rootViewController: apptVC)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
} else if (type == "4") {
let storyboard: UIStoryboard = UIStoryboard(name: "Enquiry", bundle: nil)
let enqVC = storyboard.instantiateViewController(withIdentifier: "EnquiryDetailViewController") as! EnquiryDetailViewController
let navigationController = UINavigationController.init(rootViewController: enqVC)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
}
}
Above code is fetch push notification data and send to related View Controller when user tapped on it. But I've found that status bar is missing when View Controller is open. Please let me know how to fix it, thanks.
At firs glance (and without actually verifying the code) my suspicion would be that the culprit is this:
self.window = UIWindow(frame: UIScreen.main.bounds)
You are setting your window to cover the full bounds of the view. To see if this is the issue, simply change that line to the following:
var rect = UIScreen.main.bounds
rect.origin.y += 20
self.window = UIWindow(frame: rect)
And see if the issue goes away. In my code, I've simply changed the top position of the window to allow for the status bar.

Opening view controller from app delegate using swift

I am trying to create a push notification which determines which view to open according to information obtained from the push.
I have managed to get the information from the push, but I am now struggling to get the view to open
Looking at other stack overflow questions I have the following currently:
App Delegate Did finish loading:
//Extract the notification data
if let notificationPayload = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {
// Get which page to open
let viewload = notificationPayload["view"] as? NSString
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
//Load correct view
if viewload == "circles" {
var viewController = self.window?.rootViewController?.storyboard?.instantiateViewControllerWithIdentifier("Circles") as! UIViewController
self.window?.rootViewController = viewController
}
}
Currently this is failing on the var ViewController = self... line.
You have to set ViewController StoryBoardId property as below image.
open viewController using coding as below in swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("Circles") as UIViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewControlleripad
self.window?.makeKeyAndVisible()
return true
}
For iOS 13+ (based on an article by dev2qa)
Open SceneDelegate.swift and add following
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// If this scene's self.window is nil then set a new UIWindow object to it.
self.window = self.window ?? UIWindow()
// Set this scene's window's background color.
self.window!.backgroundColor = UIColor.red
// Create a ViewController object and set it as the scene's window's root view controller.
self.window!.rootViewController = ViewController()
// Make this scene's window be visible.
self.window!.makeKeyAndVisible()
guard scene is UIWindowScene else { return }
}
There is an open-source navigation utility which attempts to make this easier. Example
Swift 3:
This is my preferred approach when presenting a new viewController from the current viewController through the AppDelegate. This way you don't have to completely tear down your view hierarchy when handling a push notification or universal link
if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "someController") as? SomeController {
if let window = self.window, let rootViewController = window.rootViewController {
var currentController = rootViewController
while let presentedController = currentController.presentedViewController {
currentController = presentedController
}
currentController.present(controller, animated: true, completion: nil)
}
}
Swift 3
To present the view together with the navigation controller:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier :"InboxViewController") as! InboxViewController
let navController = UINavigationController.init(rootViewController: viewController)
if let window = self.window, let rootViewController = window.rootViewController {
var currentController = rootViewController
while let presentedController = currentController.presentedViewController {
currentController = presentedController
}
currentController.present(navController, animated: true, completion: nil)
}
First Initialize the window
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
For setting rootViewController inside AppDelegate Class
let viewController = storyBoard.instantiateViewControllerWithIdentifier("Circles") as UIViewController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
There is a swift 4 version
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewController(withIdentifier: "Circles") as UIViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewControlleripad
self.window?.makeKeyAndVisible()
return true}
In Swift 3
let mainStoryboard : UIStoryboard = UIStoryboard(name: StorybordName, bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboard.instantiateViewController(withIdentifier: identifierName) as UIViewController
if let navigationController = self.window?.rootViewController as? UINavigationController
{
navigationController.pushViewController(initialViewControlleripad, animated: animation)
}
else
{
print("Navigation Controller not Found")
}
I'd say creating UIWindow each time you want to change rootViewController is bad idea. After couple changes of rootVC (using upper solution) you are gonna have many UIWindows in your app at one time.
In my opinion better solution is:
Get new rootVC: let rootVC = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewControllerWithIdentifier("newRootVCIdentifier") as UIViewController
Set frame for new rootVC from UIScreen's bounds: rootVC.view.frame = UIScreen.mainScreen().bounds
Set new root controller for current window (here with animation): UIView.transitionWithView(self.window!, duration: 0.5, options: .TransitionCrossDissolve, animations: {
self.window!.rootViewController = rootVC
}, completion: nil)
Done!
You don't need method window?.makeKeyAndVisible(), cause this solution works on current app window.
Swift 3 SWRevealViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyBoard.instantiateViewController(withIdentifier: "SWRevealViewController") as! SWRevealViewController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destinationViewController = storyboard.instantiateViewController(withIdentifier: "LandVC") as! LandingPageVC
destinationViewController.webpageURL = NotificationAdvertisement._htmlpackagePath
destinationViewController.adID = NotificationAdvertisement._adID
destinationViewController.toneID = NotificationAdvertisement.toneID
let navigationController = self.window?.rootViewController as! UIViewController
navigationController.showDetailViewController(destinationViewController, sender: Any?.self)
SWIFT 4
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destinationViewController = storyboard.instantiateViewController(withIdentifier: "LandVC") as! LandingPageVC
destinationViewController.webpageURL = NotificationAdvertisement._htmlpackagePath
destinationViewController.adID = NotificationAdvertisement._adID
destinationViewController.toneID = NotificationAdvertisement.toneID
let navigationController = self.window?.rootViewController as! UIViewController
navigationController.showDetailViewController(destinationViewController, sender: Any?.self)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
let mainStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc : UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "LoginViewController")
let rootNC = UINavigationController(rootViewController: vc)
self.window?.rootViewController = rootNC
self.window?.makeKeyAndVisible()
}

Resources