在appdelegate中设置初始viewcontroller - swift

时间:2014-11-05 09:46:19

标签: ios

我想从appdelegate设置初始viewcontroller。我发现了一个非常好的答案,但它是在Objective C中,我很难在swift中实现同样的目标。

Programmatically set the initial view controller using Storyboards

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

    UIViewController *viewController = // determine the initial view controller here and instantiate   it with [storyboard instantiateViewControllerWithIdentifier:<storyboard id>];

    self.window.rootViewController = viewController;
    [self.window makeKeyAndVisible];

    return YES;
}

任何人都可以提供帮助吗?

我希望初始Viewcontroller依赖于使用条件语句满足的某些条件。

24 个答案:

答案 0 :(得分:247)

我使用这个帖子来帮助我将目标C转换为swift,并且它的工作完美。

Instantiate and Present a viewController in Swift

Swift 2 代码:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

    let storyboard = UIStoryboard(name: "Main", bundle: nil)

    let initialViewController = storyboard.instantiateViewControllerWithIdentifier("LoginSignupVC")

    self.window?.rootViewController = initialViewController
    self.window?.makeKeyAndVisible()

    return true
}

Swift 3 代码:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)

    let storyboard = UIStoryboard(name: "Main", bundle: nil)

    let initialViewController = storyboard.instantiateViewController(withIdentifier: "LoginSignupVC")

    self.window?.rootViewController = initialViewController
    self.window?.makeKeyAndVisible()

    return true
}

答案 1 :(得分:40)

试试这个。例如: 您应该使用UINavigationController作为初始视图控制器。然后,您可以从故事板中将任何视图控制器设置为root。

 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let navigationController:UINavigationController = storyboard.instantiateInitialViewController() as UINavigationController
    let rootViewController:UIViewController = storyboard.instantiateViewControllerWithIdentifier("VC") as UIViewController
    navigationController.viewControllers = [rootViewController]
    self.window?.rootViewController = navigationController
    return true
}

请参阅my storyboard screen.

答案 2 :(得分:21)

如果您不使用故事板,可以试试这个

var window: UIWindow?
var initialViewController :UIViewController?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    initialViewController  = MainViewController(nibName:"MainViewController",bundle:nil)

    let frame = UIScreen.mainScreen().bounds
    window = UIWindow(frame: frame)

    window!.rootViewController = initialViewController
    window!.makeKeyAndVisible()

    return true
}

答案 3 :(得分:21)

对于Swift 3,Swift 4:

从故事板中实例化根视图控制器:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // this line is important
        self.window = UIWindow(frame: UIScreen.main.bounds)

        // In project directory storyboard looks like Main.storyboard,
        // you should use only part before ".storyboard" as it's name,
        // so in this example name is "Main".
        let storyboard = UIStoryboard.init(name: "Main", bundle: nil)

        // controller identifier sets up in storyboard utilities
        // panel (on the right), it called Storyboard ID
        let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewControllerIdentifier") as! YourViewController

        self.window?.rootViewController = viewController
        self.window?.makeKeyAndVisible()        
        return true
    }

如果您想以root身份使用UINavigationController

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // this line is important
        self.window = UIWindow(frame: UIScreen.main.bounds)

        let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
        let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewControllerIdentifier") as! YourViewController
        let navigationController = UINavigationController.init(rootViewController: viewController)
        self.window?.rootViewController = navigationController

        self.window?.makeKeyAndVisible()        
        return true
    }

从xib实例化根视图控制器:

几乎相同,但不是行

let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewControllerIdentifier") as! YourViewController

你必须写

let viewController = YourViewController(nibName: "YourViewController", bundle: nil)

答案 4 :(得分:14)

Here is a good way to approach it. This example places a navigation controller as the root view controller, and puts the view controller of your choice within it at the bottom of the navigation stack, ready for you to push whatever you need to from it.

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
    // mainStoryboard
    let mainStoryboard = UIStoryboard(name: "MainStoryboard", bundle: nil)

    // rootViewController
    let rootViewController = mainStoryboard.instantiateViewControllerWithIdentifier("MainViewController") as? UIViewController

    // navigationController
    let navigationController = UINavigationController(rootViewController: rootViewController!)

    navigationController.navigationBarHidden = true // or not, your choice.

    // self.window
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

    self.window!.rootViewController = navigationController

    self.window!.makeKeyAndVisible()
}

To make this example work you would set "MainViewController" as the Storyboard ID on your main view controller, and the storyboard's file name in this case would be "MainStoryboard.storyboard". I rename my storyboards this way because Main.storyboard to me is not a proper name, particularly if you ever go to subclass it.

答案 5 :(得分:11)

我是在目标上完成的 - 希望它对你来说是有用的

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

UIViewController *viewController;

NSUserDefaults *loginUserDefaults = [NSUserDefaults standardUserDefaults];
NSString *check=[loginUserDefaults objectForKey:@"Checklog"];

if ([check isEqualToString:@"login"]) {

    viewController = [storyboard instantiateViewControllerWithIdentifier:@"SWRevealViewController"];
} else {

    viewController = [storyboard instantiateViewControllerWithIdentifier:@"LoginViewController"];
}


self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];

答案 6 :(得分:6)

禁用Main.storyboard

General -> Deployment Info -> Main Interface -> remove `Main` 
Info.plist -> remove Key/Value for `UISceneStoryboardFile` and  `UIMainStoryboardFile`

添加情节提要ID

Main.storyboard -> Select View Controller -> Inspectors -> Identity inspector -> Storyboard ID -> e.g. customVCStoryboardId

Swift 5和Xcode 11

扩展UIWindow

class CustomWindow : UIWindow {
    //...
}

由Xcode SceneDelegate.swift生成的编辑

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: CustomWindow!

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        guard let windowScene = (scene as? UIWindowScene) else { return }

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let initialViewController = storyboard.instantiateViewController(withIdentifier: "customVCStoryboardId")

        window = CustomWindow(windowScene: windowScene)
        window.rootViewController = initialViewController
        window.makeKeyAndVisible()
    }

    //...
}

答案 7 :(得分:6)

我在Xcode 8和swift 3.0中完成了希望它对你有用,并且它的工作完美。使用以下代码:

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {       
    self.window = UIWindow(frame: UIScreen.main.bounds)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let initialViewController = storyboard.instantiateViewController(withIdentifier: "ViewController")
    self.window?.rootViewController = initialViewController
    self.window?.makeKeyAndVisible()
    return true
}

如果您使用的是导航控制器,请使用以下代码:

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let navigationController:UINavigationController = storyboard.instantiateInitialViewController() as! UINavigationController
    let initialViewController = storyboard.instantiateViewControllerWithIdentifier("ViewController")
    navigationController.viewControllers = [initialViewController]
    self.window?.rootViewController = navigationController
    self.window?.makeKeyAndVisible()      
    return true
}

答案 8 :(得分:6)

Swift 4:

在didFinishLaunchingWithOptions()函数中的AppDelegate.swift中添加这些行......

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // Setting the Appropriate initialViewController

    // Set the window to the dimensions of the device
    self.window = UIWindow(frame: UIScreen.main.bounds)

    // Grab a reference to whichever storyboard you have the ViewController within
    let storyboard = UIStoryboard(name: "Name of Storyboard", bundle: nil)

    // Grab a reference to the ViewController you want to show 1st.
    let initialViewController = storyboard.instantiateViewController(withIdentifier: "Name of ViewController")

    // Set that ViewController as the rootViewController
    self.window?.rootViewController = initialViewController

    // Sets our window up in front
    self.window?.makeKeyAndVisible()

    return true
}

现在,例如,当我们想要将用户驱动到登录屏幕或初始设置屏幕或返回到应用程序的主屏幕等时,我们会做很多次这样的事情。如果你想做某事就像这样,你可以把这一点作为一个岔路口。

想一想。你可以在NSUserDefaults中存储一个值,例如持有userLoggedIn布尔值和if userLoggedIn == false { use this storyboard & initialViewController... } else { use this storyboard & initialViewController... }

答案 9 :(得分:5)

上面/下面的所有答案都会产生关于故事板中没有入口点的警告。

如果你想拥有2个(或更多)依赖于某些条件的入口视图控制器(例如 conditionVariable ),你应该做的是:

  • 在您的Main.storyboard中创建UINavigationController 不带 rootViewController,将其设置为入口点
  • 在视图控制器中创建2个(或更多)“显示”segues,为其分配一些ID,例如 id1 id2
  • 使用下一个代码:

    class AppDelegate: UIResponder, UIApplicationDelegate {
    
       var window: UIWindow?
    
       func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
           let navigationController = window!.rootViewController! as! UINavigationController
           navigationController.performSegueWithIdentifier(conditionVariable ? "id1" : "id2")
    
           return true
       }
    

希望这有帮助。

答案 10 :(得分:5)

对于新的Xcode 11.xxx和Swift 5.xx

对于新的项目结构,AppDelegate不必对rootViewController做任何事情。

那里有一个新类来处理window(UIWindowScene)类->'SceneDelegate'文件。

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        guard let window =  self.window else {return}
        // guard let _ = (scene as? UIWindowScene) else { return }

        window.rootViewController = RootViewController() // Your root view controller
        window.makeKeyAndVisible()

    }

答案 11 :(得分:3)

这是Swift 4中的完整解决方案 在didFinishLaunchingWithOptions

中实现
 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

 let isLogin = UserDefaults.standard.bool(forKey: "Islogin")
    if isLogin{
        self.NextViewController(storybordid: "OtherViewController")


    }else{
        self.NextViewController(storybordid: "LoginViewController")

    }
}

在Appdelegate.swift中的任何位置编写此函数

  func NextViewController(storybordid:String)
{

    let storyBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let exampleVC = storyBoard.instantiateViewController(withIdentifier:storybordid )
   // self.present(exampleVC, animated: true)
    self.window = UIWindow(frame: UIScreen.main.bounds)
    self.window?.rootViewController = exampleVC
    self.window?.makeKeyAndVisible()
}

答案 12 :(得分:3)

Swift 5和Xcode 11

因此在xCode 11中,窗口解决方案在appDelegate内部不再有效。他们将其移至SceneDelgate。您可以在SceneDelgate.swift文件中找到它。

您会注意到它现在有一个var window: UIWindow?

在我的情况下,我使用情节提要中的TabBarController并将其设置为rootViewController。

这是我的代码:

sceneDelegate.swift

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).

        self.window = self.window ?? UIWindow()//@JA- If this scene's self.window is nil then set a new UIWindow object to it.

        //@Grab the storyboard and ensure that the tab bar controller is reinstantiated with the details below.
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let tabBarController = storyboard.instantiateViewController(withIdentifier: "tabBarController") as! UITabBarController

        for child in tabBarController.viewControllers ?? [] {
            if let top = child as? StateControllerProtocol {
                print("State Controller Passed To:")
                print(child.title!)
                top.setState(state: stateController)
            }
        }

        self.window!.rootViewController = tabBarController //Set the rootViewController to our modified version with the StateController instances
        self.window!.makeKeyAndVisible()

        print("Finished scene setting code")
        guard let _ = (scene as? UIWindowScene) else { return }
    }

请确保像我在此处那样将其添加到正确的场景方法中。请注意,您需要为情节提要中使用的tabBarController或viewController设置标识符名称

how to set the storyboard ID

在我的情况下,我这样做是为了设置stateController来跟踪选项卡视图之间的共享变量。如果您想做同样的事情,请添加以下代码...

StateController.swift

import Foundation

struct tdfvars{
    var rbe:Double = 1.4
    var t1half:Double = 1.5
    var alphaBetaLate:Double = 3.0
    var alphaBetaAcute:Double = 10.0
    var totalDose:Double = 6000.00
    var dosePerFraction:Double = 200.0
    var numOfFractions:Double = 30
    var totalTime:Double = 168
    var ldrDose:Double = 8500.0
}

//@JA - Protocol that view controllers should have that defines that it should have a function to setState
protocol StateControllerProtocol {
  func setState(state: StateController)
}

class StateController {
    var tdfvariables:tdfvars = tdfvars()
}

注意:只需使用您自己的变量或试图跟踪的变量,我就在tdfvariables结构中列出了我的示例。

在TabController的每个视图中,添加以下成员变量。

    class SettingsViewController: UIViewController {
    var stateController: StateController?
.... }

然后在这些相同的文件中添加以下内容:

extension SettingsViewController: StateControllerProtocol {
  func setState(state: StateController) {
    self.stateController = state
  }
}

它的作用是允许您避免在视图之间传递变量的单例方法。这很容易实现依赖注入模型,从长远来看,它比单例方法要好得多。

答案 13 :(得分:3)

对于 swift 4.0

didfinishedlaunchingWithOptions 方法的 AppDelegate.swift 文件中,输入以下代码。

var window: UIWindow?


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()

    let rootVC = MainViewController() // your custom viewController. You can instantiate using nib too. UIViewController(nib name, bundle)
    //let rootVC = UIViewController(nibName: "MainViewController", bundle: nil) //or MainViewController()
    let navController = UINavigationController(rootViewController: rootVC) // Integrate navigation controller programmatically if you want

    window?.rootViewController = navController

    return true
}

希望它能正常工作。

答案 14 :(得分:2)

如果您不使用情节提要。您可以通过编程方式初始化主视图控制器。

快捷键4

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    let rootViewController = MainViewController()
    let navigationController = UINavigationController(rootViewController: rootViewController)
    self.window = UIWindow(frame: UIScreen.main.bounds)
    self.window?.rootViewController = navigationController
    self.window?.makeKeyAndVisible()

    return true
}
class MainViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .green
    }
}

还要从部署信息中删除Main

enter image description here

答案 15 :(得分:2)

以防你想在视图控制器中而不是在应用委托中执行:只需在视图控制器中获取对AppDelegate的引用,并使用右视图控制器重置它的窗口对象因为它是rootviewController。

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let yourVC = mainStoryboard.instantiateViewControllerWithIdentifier("YOUR_VC_IDENTIFIER") as! YourViewController
appDelegate.window?.rootViewController = yourVC
appDelegate.window?.makeKeyAndVisible()

答案 16 :(得分:1)

I worked out a solution on Xcode 6.4 in swift. 

// I saved the credentials on a click event to phone memory

    @IBAction func gotobidderpage(sender: AnyObject) {
 if (usernamestring == "bidder" && passwordstring == "day303")
        {
            rolltype = "1"

NSUserDefaults.standardUserDefaults().setObject(usernamestring, forKey: "username")
NSUserDefaults.standardUserDefaults().setObject(passwordstring, forKey: "password")
NSUserDefaults.standardUserDefaults().setObject(rolltype, forKey: "roll")


            self.performSegueWithIdentifier("seguetobidderpage", sender: self)
}


// Retained saved credentials in app delegate.swift and performed navigation after condition check


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

let usernamestring = NSUserDefaults.standardUserDefaults().stringForKey("username")
let passwordstring = NSUserDefaults.standardUserDefaults().stringForKey("password")
let rolltypestring = NSUserDefaults.standardUserDefaults().stringForKey("roll")

        if (usernamestring == "bidder" && passwordstring == "day303" && rolltypestring == "1")
        {

            // Access the storyboard and fetch an instance of the view controller
            var storyboard = UIStoryboard(name: "Main", bundle: nil)
            var viewController: BidderPage = storyboard.instantiateViewControllerWithIdentifier("bidderpageID") as! BidderPage

            // Then push that view controller onto the navigation stack
            var rootViewController = self.window!.rootViewController as! UINavigationController
            rootViewController.pushViewController(viewController, animated: true)
        }

        // Override point for customization after application launch.
        return true
    }



Hope it helps !

答案 17 :(得分:0)

用于Swift 4.2和5代码的代码:

        self.window = UIWindow(frame: UIScreen.main.bounds)

        let storyboard = UIStoryboard(name: "Main", bundle: nil)

        let initialViewController = storyboard.instantiateViewController(withIdentifier: "dashboardVC")

        self.window?.rootViewController = initialViewController
        self.window?.makeKeyAndVisible()

答案 18 :(得分:0)

使用来自App委托的SWRevealViewController打开一个视图控制器。

 self.window = UIWindow(frame: UIScreen.main.bounds)
 let storyboard = UIStoryboard(name: "StoryboardName", bundle: nil)
 let swrevealviewcontroller:SWRevealViewController = storyboard.instantiateInitialViewController() as! SWRevealViewController 
 self.window?.rootViewController = swrevealviewcontroller
 self.window?.makeKeyAndVisible()

答案 19 :(得分:0)

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    var exampleViewController: ExampleViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ExampleController") as! ExampleViewController

    self.window?.rootViewController = exampleViewController

    self.window?.makeKeyAndVisible()

    return true
}

答案 20 :(得分:0)

对于Swift 5 +


var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            let submodules = (
                home: HomeRouter.createModule(),
                search: SearchRouter.createModule(),
                exoplanets: ExoplanetsRouter.createModule()
            )
            
            let tabBarController = TabBarModuleBuilder.build(usingSubmodules: submodules)
            
            window.rootViewController = tabBarController
            self.window = window
            window.makeKeyAndVisible()
        }
    }

答案 21 :(得分:0)

iOS 13 +

场景代理中:

var window: UIWindow?

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options 
connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    window = UIWindow(windowScene: windowScene)
    let vc = UIViewController() //Instead of UIViewController() we initilise our initial viewController
    window?.rootViewController = vc
    window?.makeKeyAndVisible()
}

答案 22 :(得分:0)

如果我的应用程序用户已经存在于钥匙串或userdefault中,则需要更改rootviewcontroller时,我认为此答案非常有用,并且非常适合我的情况。

https://stackoverflow.com/a/58413582/6596443

答案 23 :(得分:0)

Swift 5.3 + 和 iOS 13.0 +

在“SceneDelegate.swift”中设置您的初始 ViewController // 仅

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 }
        window = UIWindow(windowScene: windowScene)
        setInitialViewController()
        window?.makeKeyAndVisible()
    }
    
    func setInitialViewController()  {
        
        // Set Story board Controller
        /*
         let storyboard = UIStoryboard(name: "Main", bundle: nil)
         let vc = storyboard.instantiateViewController(withIdentifier: "ViewController")
         */
        
        // Set Custom Xib
        let vc = FrontVC(nibName: "FrontViewController", bundle: nil)
        
        // Navigation Controller
        let nav = UINavigationController(rootViewController: vc)
        nav.isNavigationBarHidden = true
        window?.rootViewController = nav
    }