Load A View Controller programmatically from a UIView - ios

I am using the following from within a class to call a UIViewController. The UIViewController loads, but then becomes unresponsive after loading.
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let homeC = storyboard.instantiateViewController(withIdentifier:
"ViewJoeProfileController") as? ViewJoeProfileController
if homeC != nil {
homeC!.view.frame = (self.window!.frame)
self.window!.addSubview(homeC!.view)
self.window!.bringSubview(toFront: homeC!.view)
}
}
Any suggestions to make the UIViewController being loaded responsive would really help!

If you specifically want to add to the window, you should do it the proper way and add the whole ViewController:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
guard let window = UIWindow(frame: UIScreen.mainScreen().bounds) else { return true }
if let homeC = storyboard.instantiateViewController(withIdentifier: "ViewJoeProfileController") as? ViewJoeProfileController {
window.rootViewController = mainViewController
window.makeKeyAndVisible()
}
return true
}
But honestly that structure still doesn't seem correct. Why are you adding a view to the window, instead of using an initial view controller and then adding to itsviews, or segueing to different ViewControllers?.

Try using this I need to make root View Controller
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "ViewJoeProfileController") as! ViewJoeProfileController
let nav = UINavigationController(rootViewController: vc)
nav.isNavigationBarHidden = true
self.window?.rootViewController=nav
self.window?.makeKeyAndVisible()

Related

set root view controller in main storyboard

so i have this storyboard and i want the user to be shown the login view controller if he is not logged in or the tab view controller otherwise.
this is my code inside the app delegate :
`
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
UITabBar.appearance().tintColor = .white
// check user
let authListener = Auth.auth().addStateDidChangeListener { auth, user in
if user != nil {
print("USER IS NOT NIL")
userService.observeUserProfile(uid: user!.uid) { userProfile in
userService.currentUserProfile = userProfile
}
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "TabBarVC") as! UITabBarController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
} else {
print("USER IS NIL")
userService.currentUserProfile = nil
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "FirstVC") as! UIViewController
vc.modalPresentationStyle = .fullScreen
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
}
}
}
`
My problem is that if the user is not logged it looks like this:
As you can see the view is not full screen even though i specified that in the app delegate so the user can simply dismiss it and enter the main screen. Also in the tab view controller i have the main screen with a playing video and the login screen also has a playing video in the background and both videos are played at the same time XD .Any tips would be welcome.
change storyboard--> viewcontroller---> attribute inspector---> change presentation from Automatic to Full Screen
let nav = UINavigationController()
nav.navigationBar.isHidden = true
//your Controller
let first = Router.shared.splashVC()
let third = Router.shared.CustomTabbarVC()
third.selectedIndex = 0
//add multiple controller in array
nav.viewControllers = [first,third]
UIApplication.shared.keyWindow?.rootViewController = nav
UIApplication.shared.keyWindow?.makeKeyAndVisible()
First Select all ViewController and change presentation mode Automatic from Full Screen in Simulated Metrics.
Added UINavigationController in rootViewController
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "TabBarVC") as! UITabBarController
let navigationController = UINavigationController(rootViewController: vc)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = navigationController
vc.navigationController?.isNavigationBarHidden = true
self.window?.makeKeyAndVisible()

How to go from appDelegate to viewController [duplicate]

This question already has answers here:
Storyboard - refer to ViewController in AppDelegate
(5 answers)
Closed 4 years ago.
if i have two viewControllers and i want when condition succeeded i want to go to another ViewController.
but i want to check every time the app launched so i stored the value on userDefaults and in appDelegate i checked for this value.
when i print the value i get it but i can not go to the desired controller.
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let active:Bool = defaults.bool(forKey: "activeBooking")
if active {
print("active \(active)")
let rootViewController = self.window!.rootViewController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Final", bundle: nil)
let setViewController = mainStoryboard.instantiateViewController(withIdentifier: "finalBooking") as! BookingFromCurrentLocationVC
rootViewController?.navigationController?.popToViewController(setViewController, animated: false)
}
return true
}
i print the value in other controller and it return me true(my value) so why i can not go to another controller
You can try this:
In appDelegate and in didFinishLaunching
You can store this value in UserDefault and then check the condition:
if condition == true{
goToVC1()
}else{
goToVC2
}
func goToVC1() {
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let ObjVC1: ViewController = storyboard.instantiateViewController(withIdentifier: "VC1") as! VC1
let navigationController : UINavigationController = UINavigationController(rootViewController: ObjVC1)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
func goToVC2() {
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let ObjVC2: ViewController = storyboard.instantiateViewController(withIdentifier: "VC2") as! VC2
let navigationController : UINavigationController = UINavigationController(rootViewController: ObjVC2)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
Add a segue from Navigation controller to desired View Controller (with segue identifier "finalBookingVC") and replace the code inside your if condition with:
self.window?.rootViewController!.performSegue(withIdentifier: "finalBookingVC", sender: nil)
You can initiate your view controller in AppDelegate as below.
Perform your condition check and set the StoryboardID and ViewControllerID as per your requirement.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
//check your condition here and change the Storyboard name and ViewController ID as required
let vc = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "HomeVCID") as! HomeController
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
return true
}
The first thing you need to check if an application is active and already open (top controller is finalBookingVC) then no need to do anything,
second thing finalBookingVC if already available in a stack then no need to push at that time you need to pop view controller.
If finalBookingVC is not available on the stack then you need to push this controller.
func gotoController() {
let navigationController : UINavigationController! = self.window!.rootViewController as! UINavigationController;
let arrViewController = navigationController;
if arrViewController != nil && !(arrViewController?.topViewController is finalBookingVC) {
var finalBookingVCFound:Bool = false;
for aViewController in (arrViewController?.viewControllers)! {
if aViewController is finalBookingVC {
finalBookingVCFound = true;
_ = navigationController?.popToViewController(aViewController, animated: true);
break;
}
}
if !finalBookingVCFound {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil);
let objVC:finalBookingVC = mainStoryboard.instantiateViewController(withIdentifier: "finalBookingVC") as! finalBookingVC;
navigationController?.pushViewController(objVC, animated: true);
}
}
}

Trying to Embed VC into NavigationVC from performActionFor shortcutItem via 3d touch on App icon

I have an app that is using 3d touch to jump to a certain VC in my app. The issue is that when the app is launched normally, all of my VC's are embedded into a Navigation View Controller. But since I am skipping the launch sequence and jumping right into a VC, the VC that I jump to isn't embedded into the Nav VC.
Here is what I am trying in the App Delegate
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: #escaping (Bool) -> Void) {
guard TouchActions(rawValue: shortcutItem.type) != nil else {
print("3d not working")
completionHandler(false)
return
}
print("3d touch workig")
let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let addPersonVC : AddPersonViewController = mainStoryboard.instantiateViewController(withIdentifier: "AddPerson") as! AddPersonViewController
// pass the stack to the addPersonVC
addPersonVC.coreDataStack = coreDataStack
let navController:UINavigationController = mainStoryboard.instantiateViewController(withIdentifier: "navController") as! UINavigationController
navController.pushViewController(addPersonVC, animated: true)
// self.window? = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = navController
self.window?.makeKeyAndVisible()
completionHandler(true)
}
This code works, but you when I try to leave this VC, the app just sits there unresponsive. I some how need to embedded addPersonVC into the main Nav VC that is set up in storyboard. (The embedded navigation controller was set up in storyboard, incase that matters.)
Option1: Add a Storyboard Identifier to your UINavigationController , and instantiate the UINavigationController instead.
Option2: Delete the UINavigationController from storyboard. Just initialize a new UINavigationController by code and set the rootView programatically.
I am not a Swift developer, but since you don't see the examples I wrote I did some quick pasting to help you understand the basics, try this code:
let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let addPersonVC : AddPersonViewController = mainStoryboard.instantiateViewController(withIdentifier: "AddPerson") as! AddPersonViewController
// pass the stack to the addPersonVC
addPersonVC.coreDataStack = coreDataStack
let navController:UINavigationController = mainStoryboard.instantiateViewController(withIdentifier: "navController") as! UINavigationController
navController.viewControllers = [addPersonVC]
self.window?.rootViewController?.present(navController, animated: true, completion: nil)
self.window?.makeKeyAndVisible()

Display a particular viewcontroller in Xcode/swift using if else conditional statements

I want a to have a conditional if statement to be run immediately when the app is open. Basically, it will be
if x = true {
//segue to viewcontroller1
} else {
//stay on this page
}
This will be in Xcode and coded in swift (obviously the syntax is wrong)... what is the appropriate way to write the syntax to segue to a particular view controller if the condition is true and stay on the one that normally is opened up to upon opening the app? Also, where do I put this? I considered the viewdidload method in the, normally, first displayed viewcontroller, but the variable needs to be checked before the view loads, such that the view changes to a different one if the condition is true and that one opens first instead?
Edit: I tried to set the code in the AppDelegate.swift as follows:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if x{
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let ViewController = mainStoryBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = ViewController
} else{
//same code as above but to different VC
}
return true
}
But when I run this I get an error in the appDelegate saying that "libc++abi.dylib: terminating with uncaught exception of type NSException". What is the right way to modify this code?
If you want to select the scene before presenting. You can add the following in appDelegate.swift, in application(application: UIApplication, didFinishLaunchingWithOptions):
var id = x ? "id1" : "id2"
self.window = UIWindow(frame: UIScreen.main.bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let exampleVC: UIViewController = mainStoryboard.instantiateViewController(withIdentifier: id) as UIViewController
self.window?.rootViewController = exampleVC
self.window?.makeKeyAndVisible()
Make sure you name the scenes in storyboard
If you OK with the first scene showing and then choosing to segue:
if x {
self.performSegue(withIdentifier: "id1", sender: self)
} else {
self.performSegue(withIdentifier: "id2", sender: self)
}
Again, make sure to name the segues in storyboard
Another option, use UINavigationController. Set a Navigation Controller as your root view controller
let id = x ? "id1" : "id2"
let mainStoryboard = UIStoryboard(name: "MainStoryboard", bundle: nil)
let exampleVC = mainStoryboard.instantiateViewController(withIdentifier: id) as UIViewController
let navigationController = UINavigationController(rootViewController: exampleVC)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window!.rootViewController = navigationController
self.window!.makeKeyAndVisible()

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