URLresponse is not retrieved after storing in cache using storeCachedResponse

て烟熏妆下的殇ゞ 提交于 2019-11-27 15:42:14

Welcome to the wonderful world of asynchronous caches. NSURLCache is highly asynchronous. Just because you've shoved data into it doesn't mean it is available for retrieval. You have to let the main run loop return before it will be available, and possibly even wait a little while. The failure to return a response immediately after storing it is not at all unusual. Try dispatching it after five seconds or so.

Second, your cache might be a bit on the small size for storing multi-megabyte images. Try bumping that up and see if it helps.

Finally, what do you mean when you say that you "turn off your Internet?" You say that you're getting a timeout. Normally, if you put the device into Airplane mode with all connectivity disabled, it should not sit there for any significant amount of time before failing with an error indicating no connectivity). If that isn't happening, something strange is happening, almost as if waitsForConnectivity is getting set on the session or something. (You aren't making the network requests in the background, are you? If so, try explicitly setting waitsForConnectivity to NO so that they won't wait for a connection to be available.)

Also, for this usage, you may have to strip out the Vary: Accept-Encoding header or provide a consistent user agent string. That header causes the cache to basically be per-browser. This may cause the cache to behave in unexpected ways, and is probably the cause of the weirdness you're seeing.

Note that stripping out the Vary header is a bit of a hack, and probably isn't the most correct way to fix the issue; ideally, you should tweak whatever outgoing header fields you have to tweak so that it works even with that header present. But you'd have to research it and figure out exactly what fields are needed, because I have no idea. :-)

This isn't a complete answer, but it should put you in the right direction.

The issue isn't to do with your code, I believe that it's mostly fine. The issue is regarding the response that you get from the landscapeURLString because the image is stored in Cloudflare. If you use 2 images from the same source, (e.g. try with this bear from wikipedia instead of the image from images.pexels.com) it should work.

I tried printing out the response and headers of downloading the images.pexels.com image and this is what I saw:

response: <NSHTTPURLResponse: 0x600002bf65c0> { URL: https://upload.wikimedia.org/wikipedia/commons/e/e0/Large_Scaled_Forest_Lizard.jpg } { Status Code: 200, Headers {
    "Accept-Ranges" =     (
        bytes
    );
    "Cache-Control" =     (
        "public, max-age=31536000"
    );
    "Content-Length" =     (
        997361
    );
    "Content-Type" =     (
        "image/jpeg"
    );
    Date =     (
        "Wed, 31 Oct 2018 11:38:52 GMT"
    );
    Expires =     (
        "Thu, 31 Oct 2019 11:38:52 GMT"
    );
    "Last-Modified" =     (
        "Fri, 26 Oct 2018 6:31:56 GMT"
    );
    Server =     (
        cloudflare
    );
    Vary =     (
        "Accept-Encoding"
    );
    "cf-cache-status" =     (
        HIT
    );
    "cf-ray" =     (
        "4725d67b0ae461bd-BCN"
    );
    "expect-ct" =     (
        "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\""
    );
    "x-cache" =     (
        "HIT, MISS"
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-served-by" =     (
        "cache-lax8643-LAX, cache-mad9437-MAD"
    );
} }
headers: ["Accept-Ranges": "bytes", "Content-Type": "image/jpeg", "Last-Modified": "Fri, 26 Oct 2018 6:31:56 GMT", "Vary": "Accept-Encoding", "cf-ray": "4725d67b0ae461bd-BCN", "Date": "Wed, 31 Oct 2018 11:38:52 GMT", "Server": "cloudflare", "Expires": "Thu, 31 Oct 2019 11:38:52 GMT", "x-content-type-options": "nosniff", "expect-ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", "x-cache": "HIT, MISS", "x-served-by": "cache-lax8643-LAX, cache-mad9437-MAD", "cf-cache-status": "HIT", "Content-Length": "997361", "Cache-Control": "public, max-age=31536000"]

There's probably something in there that is trying to match the request URL with a response field that's causing the cache miss, but I'm not knowledgable enough to know what it is. Somebody else can probably catch it for you (hence why I said that this answer is incomplete).

slobodans

I resolved this problem by replacing first guard inside dataTask completionHandler with:

guard error == nil else {
  print(error)

  if let cr = session.configuration.urlCache?.cachedResponse(for: urlRequest){
     let image = UIImage(data: cr.data)
     DispatchQueue.main.async {
       self?.imageView.image = image
     }
   }

   return
}

If request fails, it will take cached response for that request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!