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

Preload ViewController on application start

我有一个很重的 UIViewController,它在 viewDidLoad 中加载多个图像(所以它只在第一个控制器访问时调用一次)。 加载它需要 5-10 秒,我想减少它,在应用程序启动时从某个地方预加载它。

我已经完成研究并尝试访问控制器的 view 属性,以便它加载到 AppDelegatedidFinishLaunchingWithOptions 方法中,它确实做到了(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
}

我如何预加载一个巨大的 UIViewController 以便在打开时不需要太多加载?它持有的数据是完全静态的,因此任何解决方案都适用。

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

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

您可能需要实施一些状态跟踪,以确保当您向加载程序请求数据时,它将开始加载,或者如果加载已经在进行中则等待。

还有一个好处,您还可以在后台队列中实现加载,这样它就不会阻塞 UI。

虽然您的解决方案不会帮助您实现更快的加载速度,但您必须完成繁重的工作 async :

您解释的问题是,当您 instantiateViewController 它创建了一个与您稍后将看到的完全不同的新视图控制器。因此,您必须 get 而不是那样。一种方法是从 appDelegate 中的主 window 访问它:

let controller = window?.rootViewController as? modeDescriptionViewController

然后你可以强制它加载它的视图(完全不推荐)

Controller.loadView()

然后自动调用viewDidLoad

提示:如果window没有加载,你可以在上面调用makeKeyAndVisible()

wvteijlingen 的回答应该是可行的方法,将繁重的(业务)逻辑从控制器提取到专用的 class 中是最佳解决方案。但是,如果重构会很复杂,那么您可以按照下面描述的方法进行操作。


您在didFinishLaunchingWithOptions中创建的控制器实例一旦方法退出就会丢失,因此它的视图和视图加载的内容将被丢弃。如果要重用该实例,可以将其存储到 属性 of 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