每次启动时 UIWebView 白屏,同时预加载所有选项卡

UIWebView white screen on every launch while preloading all tabs

在提出我的问题之前,我想提一下我曾尝试寻找解决方案 here and here
我正在创建一个混合应用程序,它使用本机 UIWebView 来呈现响应式设计的 Web 应用程序。以下是问题描述:
1. 我有一个 UITabBarController.
2. 每个选项卡都有一个UIWebView.
3. 我必须预加载所有选项卡。
4. 我正在显示 UIActivityIndicator,直到内容加载到第一个选项卡上。
5. 白屏出现约 8-10 秒,然后开始显示内容。
我会很高兴看到这个时间变成2-4秒

以下是我的实现:

[self performSelectorOnMainThread:@selector(loadAllTabs) withObject:nil waitUntilDone:YES];

-(void) loadAllTabs
{
    for(UIViewController * viewController in  self.viewControllers){
        if(![[NSUserDefaults standardUserDefaults]boolForKey:@"isSessionExpired"])
        {
            if((int)[self.viewControllers indexOfObject:viewController] != 4)
            {
                viewController.tabBarItem.tag = (int)[[self viewControllers] indexOfObject:viewController];
                [viewController view];
            }
        }
    }
}

在 WebView 控制器的 viewDidLoad 我有:

[_tgWebView loadRequest:[NSURLRequest requestWithURL:homeURL]];  

我很期待 suppressesIncrementalRendering,但由于我预加载了所有选项卡,所以这不起作用。 由于我的应用程序支持iOS 7+,因此WKWebView无法在此处应用。
我还想到了 increasing 启动图像持续时间,但了解到这不是一个好的做法。
这可以使用 GCD 实现吗?
请指出我实现中的缺陷,以便我的应用程序具有更好的性能。

首先,隐藏每个选项卡上的 UIWebView,直到它完成加载,然后显示它。在 UIWebView 下,你可以有一些占位符图像来描述它的加载。然后使用 webViewDidFinishLoad 委托方法在完成加载时显示 Web 视图。这种方法将是非阻塞的。

- (void)webViewDidFinishLoad:(UIWebView *)webview
{
    if (webview.isLoading)
        return;
    else
        webView.hidden = false;
}

其次,预加载第一个选项卡,然后在显示第一个选项卡的同时加载后续选项卡。您可以通过将以下代码放在第一个选项卡的 viewDidLoad 方法中来做到这一点:

// Preload the subsquent tabs
for (UIViewController *aVC in self.tabBarController.viewControllers)
    if ([aVC respondsToSelector:@selector(view)] && aVC != self)
        aVC.view;

这样,附加选项卡 Web 视图将以非阻塞方式在后台加载。您可以将它与加载时隐藏 Web 视图相结合,以防用户在加载页面之前导航到其他选项卡。

我用三个选项卡对此进行了测试,效果很好。

所以第一个视图控制器看起来像这样: @implementation FirstViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Load the website
    [self loadWebView];

    // Preload the subsquent tabs
    for (UIViewController *aVC in self.tabBarController.viewControllers)
        if ([aVC respondsToSelector:@selector(view)] && aVC != self)
            aVC.view;
}

-(void)loadWebView
{
    // Create Request
    NSURL *url = [NSURL URLWithString:@"http://anandTech.com"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    // Load the page
    [webView loadRequest:request];
}

- (void)webViewDidFinishLoad:(UIWebView *)webview
{
    if (webview.isLoading)
        return;
    else
        webView.hidden = false;
}

编辑: 删除了 GDC,因为当视图具有 WebViews

时它会崩溃

很难直接确定问题出在哪里。

首先,我建议您检查您的网络连接,方法是在同一 Wifi 上的台式机上加载该页面,看看是否是您的服务器速度太慢。

您也可以一个一个地加载您的页面,而不是同时加载所有页面,因为多个 HTTP 请求不是按 FIFO 顺序处理的,它们可能会被乱序处理,并且您的页面可能需要所有资源显示前加载。

你自己控制网页吗?您可以使用 safari inspector 检查您的网页,看看时间花在哪里,是资源加载、javascript 处理还是渲染。

post 成就了我的一天。我现在为此使用 NSNotificationCenter