1

使用场景委托,我可以设置根视图控制器。(我使用的是 Xcode 11.3 和 iOS 版本 13.3,并在 iPhone 6+ 和 iOS 12.4 上运行我的应用程序)

我想要的是当用户登录时,我需要更新根视图控制器。为此,我做了以下

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
    }
  }
}

因此,当用户登录应用程序时,我需要从标签栏中删除一个标签项并更新根视图控制器。

所以我这样做如下。

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
        }
    }
  }
}

当我这样做时,什么也没发生。用户成功登录应用后,我无法更改应用的根视图控制器?

有什么建议么?我究竟做错了什么?

4

4 回答 4

1

这就是我管理旧版本和新版本导航的方式。因此,当用户拥有最新的 iOS 时,我们需要设置根目录,sceneDelegate而对于旧版本,我们需要设置根目录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()
    }
}
于 2019-12-19T07:06:59.703 回答
0
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())
        }
    }
于 2020-10-06T13:12:33.397 回答
0

更新 Swift 5+,Xcode 13+

rootViewController根据用户是否登录进行更改,这里是完整的代码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.
    }


}
于 2021-12-14T18:35:45.400 回答
-1

PinkeshGjr 的答案的问题是它丢弃了场景提供的窗口对象。这是我觉得更好/更简单的方法:

@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()
    }
}
于 2019-12-30T20:13:36.543 回答