以编程方式设置初始视图控制器 - Swift

8

我在stackoverflow上看到了一些关于Objective-C的冗长回答,但没有Swift的回答。

如何在Swift中从一个视图控制器编程方式地更改初始视图控制器?

我认为它应该像这样:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
storyboard.setInitialViewController(identifier: ViewController())

但是,这并没有起到任何作用。第一行很好,但第二行的函数并不存在。


可能是在appdelegate中设置初始视图控制器-swift的重复问题。 - Victor Sigler
这不是重复,因为原问题询问如何在应用程序委托中完成,但这个问题询问如何从视图控制器设置初始视图控制器。 - Ankit Goel
1
你能更详细地解释一下为什么需要从另一个视图控制器设置初始视图控制器,以便更好地帮助你吗? - Victor Sigler
我添加了一个答案来澄清您的问题。 - Victor Sigler
3个回答

12

在视图控制器中执行而不是在应用程序委托中执行:只需在您的视图控制器中获取对AppDelegate的引用,并使用正确的视图控制器作为其rootViewController重置它的window对象。

步骤1: 创建一些用户可以调整的NSUserDefaults。例如,在表格视图中放置几个按钮或开关。然后当用户点击按钮时,我们改变NSUserDefaults。

@IBAction func SwitchLaunchViewtoViewController2(sender: AnyObject) {
  defaults.setObject("ViewController2", forKey: "LaunchView")
}
@IBAction func SwitchLaunchViewtoViewController1(sender: AnyObject) {
  defaults.setObject("ViewController1", forKey: "LaunchView")
}

将设置视图控制器中的几个按钮连接到这些函数,我们就开始了。

步骤2:为想要作为启动视图的所有故事板设置Storyboard ID。因此,对于每个可能是初始视图控制器的视图控制器:

- 进入您的故事板。

- 单击视图控制器。

- 在右侧侧边栏中,单击报纸样式的图标,您可以在其中控制类。

- 在"Identity"部分(第三行),选中"Use Storyboard ID"(确保打开),然后在"Storyboard ID"文本字段中键入类似于"VC1"的内容。确保为每个视图控制器选择不同的Storyboard ID。

- 对于每个视图控制器重复上述步骤。

步骤3:在AppDelegate.swift文件中设置初始视图控制器。进入您的应用程序委托的func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool部分。

将以下内容添加以从您之前创建的NSUserDefault中读取:

let defaults = NSUserDefaults.standardUserDefaults()
    if let launchview = defaults.stringForKey("LaunchView")
    {

}

这段代码查找名为“LaunchView”的NSUserDefault字符串(在第一步中创建),如果找到匹配的NSUserDefault,则将其设置为新变量launchview。

然后,在if let launchview...大括号内,我们要检查您将LaunchView设置为什么。对于您在步骤1中设置为LaunchView的每个对象(例如,在本示例中我设置了"ViewController2""ViewController1"),您都必须在此处进行检查。因此,在这些大括号内,我们添加以下内容:

if launchview == "ViewController2" {

} else if launchview == "ViewController1" {

}

然后,在每个if语句内部,我们添加以下代码:

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) // this assumes your storyboard is titled "Main.storyboard"
let yourVC = mainStoryboard.instantiateViewControllerWithIdentifier("YOUR_VC_IDENTIFIER") as! YourViewController // 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.
appDelegate.window?.rootViewController = yourVC
appDelegate.window?.makeKeyAndVisible()

当您的应用程序在后台运行一段时间后完成加载时,它将打开所选窗口。

您的AppDelegate中的didFinishLoadingWithOptions部分可能如下所示: (不要只复制粘贴,请阅读上面的说明)

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

let defaults = NSUserDefaults.standardUserDefaults()
        if let launchview = defaults.stringForKey("LaunchView")
        {

            if launchview == "ViewController1" {

        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("VC1") as! ViewController1
        appDelegate.window?.rootViewController = yourVC
        appDelegate.window?.makeKeyAndVisible()

            } else if launchview == "ViewController2" {
                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("VC1") as! ViewController1
                appDelegate.window?.rootViewController = yourVC
                appDelegate.window?.makeKeyAndVisible()
            }

        }

        return true
   }

希望这能帮到你,非常感谢 Ankit Goel 对我帮助如此之大。阅读下面的评论以获取更多信息。

最后注意事项:如果您正在设置视图中使用开关,请确保在该设置视图控制器的viewDidLoad中从NSUserDefaults LaunchView 中读取用户上次选择的选项。


谢谢;我应该把所有代码放在我的App Delegate的哪个部分(什么区域)?如何“获取视图控制器中AppDelegate的引用并重置其窗口对象”? - owlswipe
@AnkitGoel,恐怕你的方法完全不准确。假设你已经使用了一些初始视图控制器进入应用程序。那么你什么时候放置代码呢?在它被传递后再设置初始视图控制器是错误的。这就是为什么该代码用于application:didFinishLaunchingWithOptions:的原因。 - Victor Sigler
@AnkitGoel 看起来不错,你能帮我找出如何查找视图控制器标识符吗?我的意思是,我该如何找出在“YOUR_VC_IDENTIFIER”中放什么? - owlswipe
1
@JohnRamos 打开你的Storyboard,在视图控制器上单击,在右侧窗格中单击第三个图标,设置视图控制器的自定义类,就在下面,你会看到身份检查器,可以为视图控制器设置Storyboard ID。 - Ankit Goel
如果这个回答解决了您的问题,请接受它作为答案。 - Ankit Goel
显示剩余5条评论

5

已更新至Swift 3


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

    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()

    window?.rootViewController = UINavigationController(rootViewController: ViewController())

    return true
}

2
首先,你可以在应用程序的 application:didFinishLaunchingWithOptions: 中编写代码来设置应用程序的初始视图控制器,如下所示: 你可以在其中管理所有你想要的条件,以根据不同条件显示一个或另一个 UIViewController
例如,假设你想要在应用程序中仅在第一次安装时显示演练,并在此之后显示登录屏幕,然后显示另一个屏幕,只有在第一次启动时才显示演练,在之前未登录的情况下才显示登录,否则显示另一个屏幕。当然,这可以用几种方法来处理,我只是尝试解释其中一种方法。
为此,你可以设置一个名为 SplashViewController 的控制器作为你的初始 UIViewController,并在其中显示应用程序的图像(大型图像徽标,启动画面)以及您转到其他位置时的过程。这样你就能够大大简化你的 AppDelegate 中的代码,并且更容易进行单元测试。
现在,如果你想从一个 UIViewController 跳转到另一个 UIViewController,你可以使用以下代码:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewControllerWithIdentifier("ControllerName") as! ControllerName
self.presentViewController(viewController, animated: true, completion: nil)

我希望这能对你有所帮助。

你假设代码需要在应用程序启动时运行(但问题中提到需要从视图控制器中完成此操作)。如果用户已经启动了应用程序并且需要重置窗口的根视图,则您可以触发本地通知并在应用程序委托中观察它,或者您可以简单地按照下面给出的解决方案进行操作。 - Ankit Goel
@VictorSigler非常感谢您的帮助,您确实帮助我找到了解决问题的方法(所以我会给您点赞!)。 - owlswipe
@VictorSigler 如果您对Ankit Goel的回答给出了负面评价,如果您能够撤销这个评价,那真的会很好,因为他也帮助了我!你们两个都非常有帮助。 - owlswipe
@JohnRamos 当然,现在提供的答案值得点赞 :) - Victor Sigler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接