How to fix blank screen after deleting and re-installing my app - ios

I am working on an app that requires users to log in or make an account to get to the main page. I used this code (below) in the SceneDelegate to basically tell the app that if the user is logged in, go to the main view controller, otherwise go to the login view controller. When the app is installed on a new device, this seems to work and once a user is logged in, the app takes them to the main view controller. However, I found that when the app is deleted and re-installed from a device, the app opens to a black view controller with an empty tab bar at the bottom. When I tried to debug by telling Xcode to print whether the app thinks it is signed in or not, in this case, it doesn't print that it's signed in OR out. Please let me know how to fix this if you know what the issue is. Heres the SceneDelegate code.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
if AuthManager.shared.isSignedIn {
// signed in UI
window.rootViewController = TabBarViewController()
print("signed in")
}
else {
// sign in ui
let vc = SignInViewController()
let navVC = UINavigationController(rootViewController: vc)
window.rootViewController = navVC
print("Sign IN")
}
window.makeKeyAndVisible()
self.window = window
}
func sceneDidDisconnect(_ scene: UIScene) {
}
func sceneDidBecomeActive(_ scene: UIScene) {
}
func sceneWillResignActive(_ scene: UIScene) {
}
func sceneWillEnterForeground(_ scene: UIScene) {
}
func sceneDidEnterBackground(_ scene: UIScene) {
}
}

Related

sceneDidEnterBackground is not called on iOS, swift

I am implementing the iOS app with coordinator pattern and I need to show some privacy screen when the app enters background.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var coordinator: MainCoordinator?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = scene as? UIWindowScene else { return }
if let registry = DependencyResolver.shared as? DependencyRegistry {
DependencyGraph.setup(for: registry)
}
let navController = UINavigationController()
navController.setNavigationBarHidden(true, animated: false)
coordinator = MainCoordinator(navigationController: navController)
coordinator?.start()
self.window = UIWindow.init(windowScene: scene)
window?.rootViewController = navController
window?.makeKeyAndVisible()
}
func sceneWillEnterForeground(_ scene: UIScene) {
hidePrivacyProtectionWindow()
}
func sceneDidEnterBackground(_ scene: UIScene) {
showPrivacyProtectionWindow()
}
...
// MARK: Privacy Protection
private var privacyProtectionWindow: UIWindow?
private func showPrivacyProtectionWindow() {
guard let windowScene = self.window?.windowScene else {
return
}
privacyProtectionWindow = UIWindow(windowScene: windowScene)
let storyboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "splash")
privacyProtectionWindow?.rootViewController = vc
privacyProtectionWindow?.windowLevel = .alert + 1
privacyProtectionWindow?.makeKeyAndVisible()
}
private func hidePrivacyProtectionWindow() {
privacyProtectionWindow?.isHidden = true
privacyProtectionWindow = nil
}
}
On entry, the sceneWillEnterForeground() is called. On going to background, sceneDidEnterBackground() is not called. What am I missing?
Found it myself in 10 minutes after posting the question, I used initially wrong methods. This will work for what I'm trying to achieve:
func sceneDidBecomeActive(_ scene: UIScene) {
hidePrivacyProtectionWindow()
}
func sceneWillResignActive(_ scene: UIScene) {
showPrivacyProtectionWindow()
}

How to show a ViewController in Swift only ones after downloading?

I am creating an App which features an Onboarding. This Onboarding takes place on a ViewController with only this specific purpose, that's why I only want the ViewController to show up ones after downloading the app.(the main app consists out of only one ViewController)
Here is what I've done so far:
1) I delete the storyboard entry point in the storyboard file
2) entered the Storyboard ID for each of the two ViewController
3) coded in the AppDelegate file that the onboarding ViewContoller only should show up the first time after the download
My problem: When running the app on the simulator it only shows a black screen
I already made sure that the Indentifiers and the name of the storyboard are correct.
(below my AppDelegate.swift file)
import UIKit
import Firebase
import FirebaseDatabase
import paper_onboarding
#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()
window = UIWindow(frame: UIScreen.main.bounds)
let sb = UIStoryboard(name: "Main", bundle: nil)
var initialViewController = sb.instantiateViewController(withIdentifier: "Onboarding")
let userDefaults = UserDefaults.standard
if userDefaults.bool(forKey: "onboardingComplete") {
initialViewController = sb.instantiateViewController(withIdentifier: "MainApp")
}
window?.rootViewController = initialViewController
window?.makeKeyAndVisible()
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
``
For black screen:
Have you checked MAIN INERFACE in General tab of project's target? It should be set to one of the storyboard choosing from the dropdown. Also check if Launch Screen File have the LaunchScreen or any other required storyboard selected.
For Onboarding as the first view:
Main interface should be given to the storyboard where the onboarding view controller is and then assigning that view as the initial view controller.
Let me know if you don't understand the logic.
The solution for this problem is not to use the AppDelegate.swift file but the SceneDelegate.swift file.
below my SceneDelegate.swift file
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
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).
let sb = UIStoryboard(name: "Main", bundle: nil)
var initialViewController = sb.instantiateViewController(withIdentifier: "Onboarding")
let userDefaults = UserDefaults.standard
if userDefaults.bool(forKey: "onboardingComplete") {
initialViewController = sb.instantiateViewController(withIdentifier: "MainApp")
}
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = initialViewController
self.window = window
window.makeKeyAndVisible()
}
guard let _ = (scene as? UIWindowScene) else { return }
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}

Update root view controller after user login + iOS 13 and later

Using scene delegate I'm able to set the root view controller.(I'm using Xcode 11.3 and iOS version 13.3 and running my app on iPhone 6+ with iOS 12.4)
What I want is when user login, I need to update the root view controller. For that I did the following
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
static let shared = SceneDelegate()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//some code is here
}
}
#available(iOS 13.0, *)
extension SceneDelegate {
func setRootViewControllerBasedOnLogin() {
if let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogin"), isLoggedIn {
let tabbar = UIStoryboard(name: "Other", bundle: nil).instantiateViewController(withIdentifier: "Tabbar") as! UITabBarController
if var vcs = tabbar.viewControllers {
vcs.remove(at: 2)
tabbar.viewControllers = vcs
}
self.window?.rootViewController = tabbar
} else {
//other stuff
}
}
}
So when user login in to the app I need to remove a tab item from tab bar and update the root view controller.
So I'm doing as follows.
func processLogin() {
//performing login in this method so when login successful we setting root view controller
callLoginAPI { response in
if response.isSuccess {
UserDefaults.standard.set(true, forKey: "isLogin")
if #available(iOS 13.0, *) {
SceneDelegate.shared.setRootViewControllerBasedOnLogin()
} else {
// Fallback on earlier versions
}
}
}
}
When I'm doing this nothing happened. I'm not able to change the root view controller of the app after user successfully login into the app?
Any suggestions? what am I doing wrong?
This is how I managed navigation for both the older version and the new version. So when the user has the latest iOS we need to setup root from sceneDelegate and for older version we need to setup root from appDelegate
AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13, *) {
} else {
setupRoot()
}
return true
}
// MARK: UISceneSession Lifecycle
#available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
#available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}
func setupRoot() {
//Setup Your Root Here
//window?.rootViewController = objNavigationVC
//window?.makeKeyAndVisible()
}
}
SceneDelegate.swift
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window = window
appDelegate.setupRoot()
}
}
func presentYourView(from view: YourViwe) {
if #available(iOS 13, *) {
let mySceneDelegate = view.view.window?.windowScene?.delegate
if let sceneDelegate = mySceneDelegate as? SceneDelegate {
sceneDelegate.changeRootViewController(newViewController())
}
} else {
(UIApplication.shared.delegate as? AppDelegate)?.changeRootViewController(newViewController())
}
}
Update Swift 5+ , Xcode 13+
To change rootViewController depending upon user has logged in or not, here is the full code for SceneDelegate
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
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).
guard let _ = (scene as? UIWindowScene) else { return }
if UserDefaultHelper.isLoggedIn! {
print("User logged in")
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) // this assumes your storyboard is titled "Main.storyboard"
let yourVC = mainStoryboard.instantiateViewController(withIdentifier: "CustomerMainViewController") as! CustomerMainViewController // inside "YOUR_VC_IDENTIFIER" substitute the Storyboard ID you created in step 2 for the view controller you want to open here. And substitute YourViewController with the name of your view controller, like, for example, ViewController2.
self.window?.rootViewController = yourVC
self.window?.makeKeyAndVisible()
}
else {
print("User Not logged in")
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
The problem with PinkeshGjr's answer is that it discardings the window object provided by the scene. Here's what I feel is a better/simpler approach:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
static var current: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13, *) {
} else {
window = UIWindow();
setUpRoot()
}
return true
}
func setUpRoot() {
window?.rootViewController = ViewController(nibName: nil, bundle: nil)
window?.makeKeyAndVisible()
}
}
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { fatalError() }
let firstWindow = windowScene.windows.first ?? UIWindow(windowScene: windowScene)
AppDelegate.current.window = firstWindow
AppDelegate.current.setUpRoot()
}
}

I am trying to get the rootViewController from the AppDelegate using the didFinishLoadingWithOptions method, but I can't access the window

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let navController = window.rootViewController as? UINavigationController,
let personController = navController.controllers[0] as? PeopleTableViewController{
print("something")
}
return true
}
But it is giving me an error, it is not recognizing the window property of the AppDelegate, did they change with IOS 13 because it works in my IOS 12 project
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "DataModel")
container.loadPersistentStores { description, error in
if let error = error {
fatalError("Unable to load persistent stores: \(error)")
}
}
return container
}()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let navController = window?.rootViewController as? UINavigationController,
let personController = navController.viewControllers[0] as? PeopleTableViewController{
personController.persistentContainer = persistentContainer
print("Nailed it ")
} else {
print("Sorry")
}
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
func applicationWillTerminate(_ application: UIApplication) {
persistentContainer.saveContextIfNeeded()
}
}
This is how my AppDelegate class looks
Here is how you set App's initialView Controller/rootViewController inside Scene Delegate class (this class handles Application Lifecycle Methods which were earlier handled by AppDelegate).
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let initialViewController = UIStoryboard(name: "Storyboard", bundle: nil).instantiateViewController(identifier: "DatePicker") as! DatePicker
let navigation = UINavigationController(rootViewController: initialViewController)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = tabBarCnt
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
print("App entered Background")
}
}
I found out a way around. instead of putting your code in didFinsishLoadingWithOptions method, getting the UIview comptroller's persistentContainer variable and then passing the persistentContainer in AppDelegate. you can just add this to the top of the view Controller.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.context
if you want the appDelegate you can access like this
let AppDelegate = UIApplication.shared.delegate as! AppDelegate
This works both IOS12 and IOS13 so, you don't have to change your code

How do you pass data from a custom url scheme to Views in SwiftUI?

There's no shortage of tips and tutorials on handling custom URL schemes in iOS. What ALL fail to do is actually show you how to pass data parsed from those URLs to your app/views. Yea, I can use a global variable, but that's not the "right" way and plus if you want your Swift view to react to a change in that global variable, you can't.
For example, I have,
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>){
let urlContext = URLContexts.first // Because I don't know how to properly deal with Sets
if let url = urlContext?.url{
guard let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
let params = components.queryItems else {
print("Invalid URL or album path missing")
return
}
if let token = params.first(where: { $0.name == "token" })?.value {
print("Token: \(token)")
MyGlobalToken = token
}
}
}
You'll see the MyGlobalToken option in there which works, but I can't respond to a change in that variable. Do I have to do something with the self.window?.rootViewController but I can't find any documentation on what to do. Or do you set up a "notification" so that you view responds? Or is this not implemented yet in SwiftUI?
FWIW I'm new to iOS development.
Here is a great blog to learn about SceneDelegate in iOS 13.
First answer is not a great answer.
If you run your app from a completely inactive state -- i.e. when you run it from XCode aka when it's restarted or not running in the background -- the app will call the func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) method to initialize the scenes infrastructure.
If you are running your app in the background when you point to the URL in Safari the app will call the func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) method.
In order to be thorough, you will have to attempt to get the url parameters in both methods. You can pass this query to the AppDelegate for future use by ViewControllers in both methods as well.
NOTE: If the first ViewController the app opens needs the URL query information you will need to do a few extra steps. To get your ViewControllers to actually update with the information, you will need to use the sceneDidBecomeActive() method for when the app is run from an inactive state/in the background. This method will have to call a method in the ViewController in order for it to pull the variable from the app delegate when the user enters your app. In this case I used viewDidLoad() methods to pull the updated variable from the AppDelegate.
Below is the full code for reference:
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
let appDelegate = UIApplication.shared.delegate as! AppDelegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
appDelegate.query = connectionOptions.urlContexts.first?.url.query ?? "No query"
guard let _ = (scene as? UIWindowScene) else { return }
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
appDelegate.query = URLContexts.first?.url.query
}
func sceneDidDisconnect(_ scene: UIScene) {}
// Only needed if first ViewController needs updated AppDelegate Variable
func sceneDidBecomeActive(_ scene: UIScene) {
self.window?.rootViewController?.viewDidLoad()
}
func sceneWillResignActive(_ scene: UIScene) {}
func sceneWillEnterForeground(_ scene: UIScene) {}
func sceneDidEnterBackground(_ scene: UIScene) {
(UIApplication.shared.delegate as? AppDelegate)?.saveContext()
}
}
I had many trouble in this problem.
I don't know many things in IOS.
But There is no answer. I write it.
If you don't use sceneDelegate, You may use your global variable.
(I don't know why it doesn't work)
For this, I do like below.
Delete scenedelegate.swift.
delete sceneDelegate thing in Info.plist
initialLize check variable
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
UserDefaults.check = ""
return true
}
Add lines in Appdelegate for setting global variable.
open func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
//set Global variable
// ... You should add check url for your application ...
UserDefaults.check = "checked"
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if let uservc = self.storyboard?.instantiateViewController(withIdentifier: "MainViewController") as? MainViewController
{
if #available(iOS 13.0, *) {
uservc.isModalInPresentation = true
}
uservc.debugText.text = "This is openUrl State"
self.present(uservc, animated: false) {
}
}
}
Make IntroViewController and MainViewController
IntroViewController is rootviewcontroller.
and MainViewController is second view controller.
if check variable is "checked", Viewdidload in IntroView is not excuted.
and this time is application-open is excuted with safari or chrome.
//IntroViewController
class IntroViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
if UserDefaults.check.elementsEqual("") {
if let uservc =
self.storyboard?.instantiateViewController(withIdentifier: "MainViewController") as? MainViewController
{
if #available(iOS 13.0, *) {
uservc.isModalInPresentation = true
}
uservc.debugText.text = "This is normal State"
self.present(uservc, animated: false) {
}
}
}
}
6.Global Variable
//UserDefaults.swift
import Foundation
fileprivate let keyCheck = "keyCheck"
extension UserDefaults {
static var check: String {
get {
return UserDefaults.standard.string(forKey: keyCheck) ?? ""
}
set(value) {
UserDefaults.standard.set(value, forKey: keyCheck)
UserDefaults.standard.synchronize()
}
}
}
When I use this logic in scenedelegate, It didn't work well.(I couldn't check "check variable".)

Resources