预加载——UIViewController

预加载作为常规性能优化手段,在所有性能敏感的场景都有使用。预加载数据、视图防止在真正使用的时候让用户等待,提高用户体验。

在 iOS 的优化方案中,预加载是非常常见的手段,多见于:预加载图片、配置文件、离线包等业务资源。这些都属于资源文件,我们总能找到合适的方式来进行预加载——多线程操作。但是,对于开发中最常见的 UIViewController 我们却很少能看到有对其预加载的策略。

UIViewController 预加载探究

UITabBarController 作为 ViewController 容器的时候,TabBarController 显示后,只会默认 load TabBarController 的第一个 ViewController(或者selectedViewController)的 View,只有在点击 tabbar 或者设置 selectedViewController,selectedIndex 时候,才会调用想用的 ViewController 的 loadView 与 viewDidLoad。
当项目遇到某个 tabbar 下需要预加载提升体验的时候,就需要进行相关处理。
首先在 tabbarcontroller 下获取到要预加载的vc

1
2
3
4
5
6
7
for(UINavigationController *nav in  self.viewControllers){
if ([self.viewControllers indexOfObject:nav] == 2) { // 指定需要加载的vc
UIViewController *viewController = nav.viewControllers.firstObject;
[viewController loadViewIfNeeded]; // 让其调用viewdidload
// __unused UIView *view = nav.view;
}
}

这样打开想应的 tabbar 就会发现页面已加载完成。

1
2
3
4
loadViewIfNeeded
Loads the view controller’s view if it has not yet been loaded.

- (void)loadViewIfNeeded API_AVAILABLE(ios(9.0));

说明

controller 的 view 是懒加载,只要触发了 view 的 getter 方法,那么就会触发 controller 的 viewDidLoad 方法,因此在还没有 push 到某个 controller 之前如果使用了 controller.view 那么就会触发其 viewDidLoad 方法。此时直接使用 controller 的 loadViewIfNeeded 方法很合适。

当然,我们也可以在初始化出我们需要的 controller 时,直接去获取它的 view,这样也可以触发 viewDidLoad 方法。

结论

这种方法可以帮助我们提前预热一个 UIViewController,可以加快某个 UIViewController 呈现给用户的速度。

个人认为,这种场景还是非常适合在 UITabBarController 中使用,因为 UITabBarController 的管理机制,切换 tab 时,页面也不会被销毁。

但是呢,在普通的 UINavigationController 管理的栈内,我们只是提前预热了目标 UIVIewController,当页面 pop 之后,下次还需要再次预热。

当然,我们可以将目标的 vc 缓存起来,一次预热之后,以后就可以直接使用了。

缓存 vc 的做法的话,就需要在自己的业务需求场景下去斟酌了。

  1. 缓存的 vc 肯定是需要吃掉一定的内存的。
  2. 当 vc 被缓存之后,它会保持当时的状态。我们还需要对 vc 界面的状态进行一定的管理,缓存时 vc 的状态并一定是我们希望它进去时的样子。

但是,在使用了 WebView 呈现内容时,是可以借鉴这个方法的,在进去之前,加载好 WebView 的内容,能大大的加快内容的呈现速度。