【问题标题】:UIWebView first request too slowUIWebView 第一次请求太慢
【发布时间】:2015-07-21 13:46:30
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您正在使用模拟器或任何设备?可能是您的设备上打开了一些代理。
  • @aBilal17 :我正在设备上进行测试。不止一个。我在 3 种不同的设备上对此进行了测试。
  • 请把这一行也加上,然后检查。 web.scrollView.delaysContentTouches = NO;
  • @aBilal17 : 没有区别。
  • 只有yahoo.com会发生这种情况吗?其他网站呢?

标签: ios iphone uiwebview uiwebviewdelegate


【解决方案1】:

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

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

希望这能解决疑问。

【讨论】:

  • 当大多数网站使用响应式方法,界面仅根据屏幕大小进行调整,因此没有“其他”版本的门户可供移动设备调用时,这是否重要?
  • 我不同意。我从应用程序包中显示了一个静态页面:let bundlePath = Bundle.main.bundlePath.stringByAppendingPathComponent("description.html")let url = URL(fileURLWithPath: bundlePath)let request = URLRequest(url: requestURL)webView.loadRequest(request) 那么网络和服务器延迟在哪里?
【解决方案2】:

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

【讨论】:

  • 但是第二个页面也是第一次启动app的时候加载的。该页面当时没有缓存。只有当页面被再次访问时,页面才会从缓存中加载。
【解决方案3】:

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

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

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

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

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

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

      【讨论】:

        【解决方案6】:

        在您的应用启动期间,只需在屏幕外加载带有虚拟页面的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;
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-08-08
          • 1970-01-01
          • 1970-01-01
          • 2021-06-04
          • 1970-01-01
          • 2019-10-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多