I would like to have my viewController named "DoctorInformationController" appear only when the user launches the app for the first time. Ive seen some people's answers, however i would like to know how to do this in swift please!
Thank you
This code I use that will launch a viewcontoller based on first or second launch of the app.
This in the AppDelegate.
var defaults: NSUserDefaults
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let firstLaunch = defaults.boolForKey("FirstLaunch")
if firstLaunch {
print("Not first launch.")
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewControllerWithIdentifier("navController") as! UINavigationController
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
} else {
print("First launch, setting NSUserDefault.")
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewControllerWithIdentifier("firstrunVCstoryboard") as UIViewController
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
return true
}
You would need to adapt it to fit your storyboard and viewcontrollers names.
EDIT:
This how I set the value in the first view controller to indicate that first run has completed. So that it will not show again.
self.defaults.setBool(true, forKey: "FirstLaunch")
There is no way to tell if it's the first launch built into the UIKit framework, however you can do it another way.
In AppDelegate.swift, go to applicationDidFinishLaunchingWithOptions method (the first one, usually). Now, add this:
//Check for key "first_launch" in User Defaults
if let _ = NSUserDefaults.standardUserDefaults().objectForKey("first_launch") {
//Set your own global variable to be true. Then, when your ViewController
//loads, do a popup window with that DoctorViewController thingy if the
//variable is true
//Example:
isFirstLaunch = true
//Then, set "first_launch" to be a value so your app will never call this block again
NSUserDefaults.standardUserDefaults().setObject("", forKey: "first_launch")
}
Related
All I want to do is go to the login screen if the user = nil. Otherwise it goes to the main/home section of the app which consists of the Tab Bar Controller's first view controller
Here is my app delegate:
import UIKit
import Firebase
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if Auth.auth().currentUser == nil && !UserDefaults.standard.bool(forKey: "hasViewedWalkthrough") {
let initialViewController = storyboard.instantiateViewController(withIdentifier: "WalkthroughViewController") as? WalkthroughViewController
self.window?.rootViewController = initialViewController
} else if Auth.auth().currentUser == nil && UserDefaults.standard.bool(forKey: "hasViewedWalkthrough") {
let initialViewController = storyboard.instantiateViewController(withIdentifier: "loginViewController") as? LoginViewController
self.window?.rootViewController = initialViewController
} else {
let initialViewController = storyboard.instantiateViewController(withIdentifier: "homeTabBarController") as? MainTabBarViewController
self.window?.rootViewController = initialViewController
}
self.window?.makeKeyAndVisible()
return true
}
I am not able to get to the onboarding or login screen. I am always led to the main screen. I know the screens are rendering fine if I manually set them as initial view controllers in storyboard.
I have tried numerous solutions and none of them are working.
Update
Try this:
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyBoard.instantiateViewControllerWithIdentifier("homeTabBarController") as? TabBarViewController // whatever your swift file is called
self.window?.rootViewController = storyBoard
use that code for each statement for the if statement, obviously change the names of the view controllers to the login one respectively.
For people reading this in the future, iOS 13 introduced SceneDelegate and now all UI related stuff should be configured from that point.
I faced the same issue and solved it by using this code.
The custom window should be configured from here now.
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).
guard let sceneWindow = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: sceneWindow.coordinateSpace.bounds)
window?.windowScene = sceneWindow
window?.makeKeyAndVisible()
if let navigationController = Storyboard.Main.initialViewController as? UINavigationController,
let viewController = navigationController.children.first as? CountriesViewController {
viewController.inject(CountriesViewModel(provider: CountryAPI(),
informTo: viewController),
navigator: CountriesNavigator(navigationController: navigationController))
window?.rootViewController = navigationController
}
}
so when i launch my app the first time there is a welcome ViewController. How can i set a function, that shows the second ViewController when the user launches the app the second time.
Add a Boolean in the user default in your application to check whether the application is launch first time or not. Based on this Boolean value load another ViewController in your app delegate class.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let isFirst = UserDefaults.standard.bool(forKey: “isLaunched”) // edited this after rmaddy's comment
var viewControllerWithIdentifier = "SecondViewController"
if !isFirst {
UserDefaults.standard.set(true, forKey: “isLaunched”)
viewControllerWithIdentifier = "FirstViewController"
}
let mainStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController : UIViewController = mainStoryboard.instantiateViewControllerWithIdentifier(viewControllerWithIdentifier) as UIViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
return true
}
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
The structure of my project is as follows.
Initially when the user is registering or trying to login the initial navigation controller should work and after successfully registering / loggin in the user should be taken to first tab of tab bar controller. But the issue that i am facing is that i am getting 2 navigation bars in the tab bar view. Can someone guide me how to implement this in the correct way.
Thanks in advance
At some point, I would assume that the app is able to determine whether the user loggedin or not, based on that you have to set the desired root view controller for the app.
For such a case, the best place to do that is application(_:didFinishLaunchingWithOptions:) method in the AppDelegate file:
Tells the delegate that the launch process is almost done and the app
is almost ready to run.
For simplicity, let's say that you are saving isLoggedin boolean in the UserDefault, so it could be achieved like this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// the flag for determining whether the user loggedin or not
let isLoggedin = UserDefaults.standard.bool(forKey: "K_isLoggedin")
// the desired initial view controller (based on the value of `isLoggedin`)
let initialViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: isLoggedin ? "TabbarIdentifier" : "FirstNavigationIdentifier")
// setting the app rootViewController
window?.rootViewController = initialViewController
return true
}
Note that "TabbarIdentifier" represents the tabbar controller at the storyboard and also "FirstNavigationIdentifier" represents the first navigation view controller at the storyboard.
if you are unaware of how to set the view controller identifier, checking this answer should help.
Technically speaking, setting the desired root view controller means setting the rootViewController to the main window of the app (AppDelegate window).
Make one of the two navigation controllers from tabbar to initial viewcontroller and add the following in Appdelegate's didFinishLAunching
if (isDashboardVC == nil || isDashboardVC == false)
{
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController:UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "navigationmain") as! UINavigationController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
else
{
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarIntial : UITabBarController = mainStoryboardIpad.instantiateViewController(withIdentifier: "Tabbarcontroller") as! UITabBarController
let navigationController2:UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "yourViewControllerName") as! UINavigationController
let navigationController:UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "yourViewControllerName") as! UINavigationController
let navigationController3:UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "yourViewControllerName") as! UINavigationController
tabBarIntial.viewControllers = [navigationController2, navigationController, navigationController3]
tabBarIntial.selectedIndex = 1
}
I am making an app that includes an onboarding screen inn swift. In the AppDelegate.swift I set the navigationController as the root view controller. But I have an onboarding screen and need to add that to the code also. Whenever I run the app I get Thread 1: SIGNAL SIBAGRT. Here is my code:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [ .
UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let sb = UIStoryboard(name: "Onboarding", bundle: nil)
let initialViewController = sb.instantiateInitialViewController()
window?.rootViewController = initialViewController
window?.makeKeyAndVisible()
let navigationController = window!.rootViewController as! UINavigationController
let controller = navigationController.viewControllers[0] as! AllListsViewController
controller.dataModel = dataModel
Try that:
window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(named:"Onboarding",bundle: nil)
let nvc = storyboard.instantiateInitialViewController() as? UINavigationController // since your storyboard start with a navigationController
let topVc = nvc.topViewController as? AllListsViewController // then we get the first controller associated to that navigationController
topVc?.dataModel = dataModel
window?.rootViewController = nvc // still set your navigationController as the root of your application
window?.makeKeyAndVisible()