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



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

在这种情况下一切正常,但问题是我的 43454.jpg 图像每次都可以为 5-10 MB。因此,当UIWebView加载时,它会继续加载图像约2分钟。另外,这个<img>标签可以有随机来源,即22234.jpg98734.jpg33123.jpg等等。

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

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

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

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

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

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

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

如果这种方法看起来没问题,那么我应该如何完成它(Swift 2.2)?

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

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

  1. 一旦我的应用程序加载,我就会创建一个图像 URL 数组并将其传递给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. 在我的 Web 视图
  3. 屏幕上,我最初加载了我的 Web 视图,然后使用以下代码检查缓存中的特定图像,如果找到,则将其转换为 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)');")!
    }
    }
    

希望对您有所帮助。

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

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

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

相关内容

最新更新