UIWebView第一次请求太慢

问题描述 投票:13回答:6

我正在使用UIWebView在我的应用程序中呈现Web内容。我观察到应用程序启动时的初始请求,即loadRequest,需要很长时间才能呈现内容。然而,我不跟踪的后续请求要快得多。 为了证实这一点,我创建了一个独立的应用程序,它只有一个UIWebView。这是我添加的单行代码:

[wkBrowser loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.yahoo.com"]]];

结果是一样的。加载页面大约需要15-20秒。但是,在点击网页上的任何链接时,加载下一页需要3-5秒。我确实把UIWebView委托函数didFailLoadWithError,但从来没有错误。 题:

  1. 为什么第一个Web请求这么慢?
  2. 除了缓存之外,我怎么能让它更快?
ios iphone uiwebview uiwebviewdelegate
6个回答
4
投票

主要原因是,当您调用第一次URL请求时,接收端的服务器会尝试按照请求的设备浏览器显示信息(如移动设备,桌面设备)。这是你看到一点延迟的地方。

  • 服务器需要一些时间来解析请求源浏览类型并根据浏览器类型进行响应。该值在内部从浏览器发送。移动野生动物园和桌面野生动物园有所不同。
  • 服务器收到请求后,会回复设备类型兼容页面(大多数域服务器都在内部实现响应页面)。
  • 如果您想要“无延迟情况”,请尝试调用相关的门户网站的确切移动版本。
  • 从已知类型的浏览器处理后续请求,从而减少响应的延迟。

希望这能解决疑问。


3
投票

您的第一个问题的答案如下: 当您第一次加载请求时,webview会下载并缓存所有文件,如CSS,图像等...之后,当您点击一个将您带到同一网站的另一个页面的网址时,它基本上会加载它从缓存而不是再次下载,它节省了大量的时间。


3
投票

第一次加载可能比后续加载慢的原因有很多。

首先,您的应用程序链接到动态框架。懒惰地执行动态链接解析。因此,无论何时第一次使用UIWebView,解析您在动态库中使用的符号都会产生非常小的开销。 UIWebView本身可能依赖于一些需要进行动态链接的内部库,增加了开销。

然后还有UIWebView本身的实现。 UIWebView的内部最可能涉及懒惰地初始化的数据结构。

然后是内存分配方面。无论何时加载第一页,应用程序的内存使用量都会比第二页加载时的内存使用量上升得多。分配足够的内存来处理页面加载会增加开销,但一旦完成,iOS会将此内存委托给您的应用程序一段时间,超过内存被释放的时间点,以便在应用程序更快时使应用程序运行达到其内存使用量的峰值。

有人建议您的两个页面之间可能存在缓存资源。即使两个页面都不同并且是第一次加载,它们也可能共享一个公共的css文件或一个常见的javascript文件,例如jQuery。然后浏览器可以重用这些缓存的资源。

总的来说,有很多这样的因素可以解释为什么第一页加载可能比后续页面加载慢。您可以通过在页面加载期间分析应用程序来了解更多关于UIWebView实际执行的操作。


1
投票

第一个问题的答案:当您第一次加载请求时,webview会下载并缓存所有文件,如CSS,图像等...之后,当您点击一个将您带到另一页的网址时在同一个网站上,它基本上是从缓存加载而不是再次下载,它节省了大量的时间。


0
投票

你可以在这里看看发生了什么是实现类似于以下链接的NSURLProtocol:http://www.raywenderlich.com/59982/nsurlprotocol-tutorial

并在canInitWithRequest方法中拦截您的请求。

这只会向您显示您的请求至少发生了什么。


0
投票

在您的应用程序启动期间,只需在屏幕外加载UIWebView虚拟页面。这将在真实设备上运行良好。在AppDelegates中有didFinishLaunchingWithOptions方法。

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

func loadInitialWebView() {
        var dummyWebView : UIWebView? = UIWebView(frame: UIScreen.main.bounds)
        let htmlString = "<!doctype html><html lang=en><head><meta charset=utf-8><title>dummy</title></head><body><p>dummy content</p></body></html>"
        dummyWebView?.loadHTMLString(htmlString, baseURL: nil)
        dummyWebView = nil;
    }
© www.soinside.com 2019 - 2024. All rights reserved.