在应用程序启动时预加载ViewController

时间:2019-01-31 18:59:11

标签: ios swift uiviewcontroller

我有一个沉重的UIViewController,它在viewDidLoad中加载多个图像(因此,仅在第一次访问控制器时,它被调用一次)。 它需要5到10秒钟的加载时间,我想减少它,从应用程序启动时的某个位置预加载它。

我已经完成了研究,并尝试访问控制器的view属性,以便将其加载到didFinishLaunchingWithOptions的{​​{1}}方法中,实际上它是(AppDelegate被调用),但是当我自己操作控制器时,viewDidLoad被再次调用,所有图像也被再次加载。

当前代码示例如下:

viewDidLoad

如何预装巨大的func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let storyboard = UIStoryboard(name: "Main", bundle: nil) let vc = storyboard.instantiateViewController(withIdentifier: "modeDescriptionViewController") let _ = vc.view // viewDidLoad is called here return true } ,以便在打开时不需要花费太多时间?它保存的数据是完全静态的,因此可以采用任何解决方案。

3 个答案:

答案 0 :(得分:3)

我建议从控制器中提取所有加载逻辑。创建一个DataLoader类(或结构)来进行加载并存储加载的数据。

在您的AppDelegate中实例化一个DataLoader,并指示它加载与视图控制器分离的数据。然后将此实例传递给控制器​​,以便控制器可以从加载程序访问数据。

您可能需要实现一些状态跟踪,以确保当您请求加载器提供数据时,它要么开始加载,要么等待加载是否正在进行。

一个加号,您还可以在后台队列中实现加载,以免阻塞UI。

答案 1 :(得分:1)

wvteijlingen的答案应该是解决之道,从控制器中提取繁重的(业务)逻辑到专用类中是最佳解决方案。但是,如果重构很复杂,则可以按照以下方法进行操作。


一旦方法退出,您在didFinishLaunchingWithOptions中创建的控制器实例将丢失,因此将丢弃其视图和该视图加载的内容。如果要重用该实例,可以将其存储到AppDelegate的属性中:

var modeDescriptionViewController: UIViewController!

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

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    modeDescriptionViewController = storyboard.instantiateViewController(withIdentifier: "modeDescriptionViewController")
    // loadViewIfNeeded() is cleaner
    modeDescriptionViewController.loadViewIfNeeded()
    return true
}

从这一点开始,您可以在需要时访问视图控制器:UIApplication.shared.delegate as! AppDelegate).modeDescriptionViewController

答案 2 :(得分:0)

尽管您的解决方案无法帮助您实现更快的负载,但您必须进行繁重的工作async

您所解释的问题是,当您instantiateViewController创建一个新的视图控制器时,它与以后将要看到的完全不同。因此,相反,您必须获取。一种实现方法是从appDelegate的主window中访问它:

let controller = window?.rootViewController as? modeDescriptionViewController

然后您可以强制其加载视图(完全不建议使用)

Controller.loadView()

然后它会自动调用viewDidLoad

提示:如果未加载window,则可以在其上调用makeKeyAndVisible()