UIWebView 第一次请求太慢

UIWebView first request too slow

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

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

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

  1. 为什么第一个网络请求这么慢?
  2. 除了缓存之外,我怎样才能让它更快?

第一个问题的答案如下:
当您第一次加载请求时,webview 会下载并缓存所有文件,如 css、图像等...之后,当您单击 url 时,您会转到另一个页面同一个网站,基本上都是从缓存中加载,而不是重新下载,节省了很多时间。

您可以在这里做的一件事是实现类似于以下内容的 NSURLProtocol link:http://www.raywenderlich.com/59982/nsurlprotocol-tutorial

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

这只会告诉你至少你的请求是怎么回事。

主要原因是,当你第一次调用URL请求时,接收端的服务器试图根据请求的设备浏览器显示信息,(如手机、桌面)。这是你看到一点延迟的地方。

  • 服务器需要一些时间解析请求来源浏览类型并根据浏览器类型做出响应。该值是从浏览器内部发送的。 移动版 safari 和桌面版 safari 有区别
  • 服务器在收到请求后,用设备类型兼容页面回复您,(大多数域服务器都在内部实现此响应页面)。
  • 如果您想要 "no delay situation",请尝试调用相关门户的确切移动版本。
  • 已知类型的浏览器处理后续请求,从而减少响应延迟。

希望这能解决疑问。

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

首先,您的应用程序正在 link 连接到动态框架。动态 link 解析是延迟执行的。因此,每当您第一次使用 UIWebView 时,解析您从动态库中使用的符号所涉及的开销非常小。 UIWebView 本身可能依赖于更多需要动态 linked 的内部库,增加了开销。

然后还有UIWebView本身的实现。 UIWebView 的内部很可能涉及延迟初始化的数据结构。

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

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

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

第一个问题的答案: 当您第一次加载请求时,webview 会下载并缓存所有文件,如 css、图像等...之后,当您单击 url 时,您会转到另一个页面同一个网站,基本上都是从缓存中加载,而不是重新下载,节省了很多时间。

只需加载 UIWebView 和屏幕外的虚拟页面,您的应用 launch.This 将在真实设备上运行良好。 在 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;
    }