I have added NavigationControllerScene to ViewController and made it initial viewcontroller in storyboard
code: if I use below code tap on testBtn not able to go to ViewController1. why? i want show ViewController with sidemenu and bottom tabbar thats why i have written code like this. added added same code in Appdelegate and Scenedelagate as well
Why not able to Navigate from ViewController to ViewController1?
this is my info.plist
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setUpNavigationBar(with: "Viewcontroller", isBackNeed: false)
}
@IBAction func testBtn(_ sender: UIButton){
// added same code in Appdelegate and scenedelagete as well
let home = Helper.getVcObject(vcName: .ViewController1, StoryBoardName: .Main) as! ViewController1
let menu = Helper.getVcObject(vcName: .MenuViewController, StoryBoardName: .Main) as! MenuViewController
let nav = MainNavigationController(rootViewController: home)
let sideMenu = SideMenuController(contentViewController: nav, menuViewController: menu)
Helper.replaceRootView(for: sideMenu)
}
}
and some of my custom methods:
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.compactMap({$0 as? UIWindowScene})
.first?.windows
.filter({$0.isKeyWindow}).first
enum StoryBoardNameCase: String {
case Main = "Main"
}
enum VCNameCase: String {
case MenuViewController = "MenuViewController"
case ViewController1 = "ViewController1"
}
class Helper {
static func getVcObject(vcName:VCNameCase, StoryBoardName:StoryBoardNameCase) -> UIViewController{
let storyBoard: UIStoryboard = UIStoryboard(name: StoryBoardName.rawValue, bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: vcName.rawValue)
return vc
}
static func replaceRootView(for rootViewController: UIViewController, animated: Bool = true, completion: (() -> Void)? = nil) {
if animated {
UIView.transition(with: keyWindow ?? UIWindow(), duration: 0.5, options: .transitionCrossDissolve, animations: {
let oldState: Bool = UIView.areAnimationsEnabled
UIView.setAnimationsEnabled(false)
keyWindow?.rootViewController = rootViewController
keyWindow?.makeKeyAndVisible()
UIView.setAnimationsEnabled(oldState)
}, completion: { (finished: Bool) -> () in
completion?()
})
} else {
keyWindow?.rootViewController = rootViewController
keyWindow?.makeKeyAndVisible()
}
}
EDIT: AppDelegate: code added same code in SceneDelegate as well
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let home = Helper.getVcObject(vcName: .ViewController1, StoryBoardName: .Main) as! ViewController1
let menu = Helper.getVcObject(vcName: .MenuViewController, StoryBoardName: .Main) as! MenuViewController
let nav = MainNavigationController(rootViewController: home)
let sideMenu = SideMenuController(contentViewController: nav, menuViewController: menu)
Helper.replaceRootView(for: sideMenu)
SideMenuController.preferences.basic.menuWidth = UIScreen.main.bounds.width * 0.8
return true
}
SceneDelegate code:
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).
let home = Helper.getVcObject(vcName: .ViewController1, StoryBoardName: .Main) as! ViewController1
let menu = Helper.getVcObject(vcName: .MenuViewController, StoryBoardName: .Main) as! MenuViewController
let nav = MainNavigationController(rootViewController: home)
let sideMenu = SideMenuController(contentViewController: nav, menuViewController: menu)
Helper.replaceRootView(for: sideMenu)
SideMenuController.preferences.basic.menuWidth = UIScreen.main.bounds.width * 0.8
}
if you are using in info plist from "Application Scene Manifest" you should define your root view controller in SceneDelegate:
So you define your LoginViewController As rootViewController on SceneDelegate
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: scene)
window?.rootViewController = yourLoginVC
window?.makeKeyAndVisible()
}
func initNewMainVC(rootVC: UIViewController) {
window?.rootViewController = rootVC
window?.makeKeyAndVisible()
}
}
in your class:
static func replaceRootView(for rootViewController: UIViewController, animated: Bool = true, completion: (() -> Void)? = nil) {
let scene = UIApplication.shared.connectedScenes.first
if let sceneDelegate: SceneDelegate = (scene?.delegate as? SceneDelegate) {
sceneDelegate.initNewMainVC(rootVC: rootViewController)
}
}
but if you use from AppDelegate means you don't use from SceneDelegate and don't have "Application Scene Manifest" in the info.plist:
you should define all of that defined on SceneDelegate to Appdelegate and set it on appdelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = yourLoginVC
self.window?.makeKeyAndVisible()
return true
}
func initNewMainVC(rootVC: UIViewController) {
window?.rootViewController = rootVC
window?.makeKeyAndVisible()
}
}
in your class:
static func replaceRootView(for rootViewController: UIViewController, animated: Bool = true, completion: (() -> Void)? = nil) {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.initNewMainVC(rootVC: rootViewController)
}
}
you should use One of them SceneDelegate or AppDelegate