使用本地(缓存)源替换UIWebView(通过Web服务加载)<img/>标记源

时间:2017-03-03 19:23:41

标签: ios swift caching uiwebview

我正在开发一个app(swift),我需要在UIWebView中加载一个网页。在UIWebView中,有一个<img src="http://www.example.com/uploads/43454.jpg" />元素。

在这种情况下一切正常,但问题是我的43454.jpg图像每次都可以是5-10兆字节。因此,当UIWebView加载时,它会继续加载图像大约2分钟。此外,此<img>代码可以包含随机来源,即22234.jpg98734.jpg33123.jpg等。

因此,为了解决这种情况,我尝试使用以下方法:

  1. 列出我们需要在UIWebView中显示的所有可能图像,在应用程序启动时下载并缓存它们(为此目的使用Kingfisher库)。

  2. 当我的UIWebView最初加载我的网址时,它没有任何内容<img>元素src属性,但有一个data-image-name="22234.jpg"属性 - 值对。< / p>

  3. 现在,当UIWebView完成加载其内容时,请从data-image-name属性中获取图像名称值。

  4. 检查缓存中的该图像,并使用缓存中的该图像更新<img>元素的src属性。

  5. 这样UIWebView就不会一遍又一遍地下载图像。

    注意:假设UIWebView自动管理资源缓存。所有其他文件类型*.js*.css正在被正确缓存,而不是一次又一次地加载。同样不适用于图像,不知道为什么。

    如果这种方法似乎没问题,那么我应该如何实现它(Swift 2.2)?

    任何快速帮助将不胜感激。感谢

2 个答案:

答案 0 :(得分:1)

在我的一个项目中,这似乎是相同的情况。我有完全相同的情况。我将在此处粘贴我的代码,可能会帮助您找到解决方案。

  1. 我的应用加载后,我会创建一个图像网址数组并将其传递给Kingfisher库,以下载并缓存所有图像(到磁盘)。

    for url in response {
       let URL = NSURL(string: url as! String)!
       self.PlanImagesArray.append(URL)
    }
    
    let prefetcher = ImagePrefetcher(
    urls: self.PlanImagesArray,
    optionsInfo: nil,
    progressBlock: {
        (skippedResources, failedResources, completedResources) -> () in
            print("progress resources are prefetched: \(completedResources)")
            print("progress resources are failedResources: \(failedResources)")
            print("progress resources are skippedResources: \(skippedResources)")
                },
    completionHandler: {
        (skippedResources, failedResources, completedResources) -> () in
            print("These resources are prefetched: \(completedResources)")
            print("These resources are failedResources: \(failedResources)")
            print("These resources are skippedResources: \(skippedResources)")
    
            self.activityLoadingIndicator.stopAnimating()
    })
    
    prefetcher.start()
    
  2. 在我的网页视图屏幕上,我最初加载了我的网页视图,然后使用以下代码检查缓存中的特定图像,如果发现将其转换为base64字符串并将其放回src属性元素。

    func webViewDidFinishLoad(webView : UIWebView) {
        //UIApplication.sharedApplication().networkActivityIndicatorVisible = false
        print("webViewDidFinishLoad")
    
        let xlinkHref = webView.stringByEvaluatingJavaScriptFromString("document.getElementById('background_image').getAttribute('xlink:href')")
    
        //print("xlink:href before = \(webView.stringByEvaluatingJavaScriptFromString("document.getElementById('background_image').getAttribute('xlink:href')"))")
    
        if xlinkHref == "" {
    
            let imageCacheKey = webView.stringByEvaluatingJavaScriptFromString("document.getElementById('background_image').getAttribute('data-cache-key')")
            let imageCachePath = ImageCache.defaultCache.cachePathForKey(imageCacheKey! as String)
            var strBase64:String = ""
    
            webView.stringByEvaluatingJavaScriptFromString(
                "var script = document.createElement('script');" +
                "script.type = 'text/javascript';" +
                "script.text = \"function setAttributeOnFly(elemName, attName, attValue) { " +
                "document.getElementById(elemName).setAttribute(attName, attValue);" +
                "}\";" +
                "document.getElementsByTagName('head')[0].appendChild(script);"
            )!
    
            if(imageCachePath != "") {
    
                ImageCache.defaultCache.retrieveImageForKey(imageCacheKey! as String, options: nil) { (imageCacheObject, imageCacheType) -> () in
    
                let imageData:NSData = UIImageJPEGRepresentation(imageCacheObject!, 100)!
                strBase64 = "data:image/jpg;base64," + imageData.base64EncodedStringWithOptions(.EncodingEndLineWithCarriageReturn)
                webView.stringByEvaluatingJavaScriptFromString("setAttributeOnFly('background_image', 'xlink:href', '\(strBase64)');")!    
            }
    
        } else {
    
            webView.stringByEvaluatingJavaScriptFromString("setAttributeOnFly('background_image', 'xlink:href', '\(imageCacheKey)');")!
    
        }
    
    }
    
  3. 希望它有所帮助。

答案 1 :(得分:0)

听起来你基本上是在说#34;我知道图像是提前的,所以我不想等待UIWebView每次都从服务器加载它们。我希望html使用我的本地副本。&#34;

虽然它是一个黑客,但我的第一个想法是:

  1. 有2个UIWebViews:一个对用户可见,另一个是隐藏的。
  2. &#34;触发&#34;隐藏的UIWebView中的真实页面。当HTML到达你时......
  3. 创建一个新字符串,即该HTML的副本,但使用<img src="http://...替换为<img src=\"file://...并指向磁盘上正确图像的图像标记。
  4. 现在告诉可见的UIWebView加载您在步骤3中构建的HTML字符串。