URLresponse não é recuperado após armazenar no cache usando storeCachedResponse

Objetiv

Estou tentando injetar dados / resposta de URLRequest nooutr URLRequest no meu cache.

Configuraçã

Este é apenas um código de exemplo. Está pronto para ser despejado em um projeto.

O que estou tentando fazer é usar a resposta + dados recuperados do meulandscapeURLString solicitação de rede ... armazenar no cache da minha sessãopara meu lagartoURLString request.

import UIKit

class ViewController: UIViewController {

    lazy var defaultSession : URLSession = {
        let urlCache = URLCache(memoryCapacity: 500 * 1024 * 1024, diskCapacity: 500 * 1024 * 1024, diskPath: "something")
        let configuration = URLSessionConfiguration.default
        configuration.urlCache = urlCache
        let session = URLSession(configuration: configuration)

        return session
    }()
    lazy var downloadLizzardbutton : UIButton = {
        let btn = UIButton()
        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.setTitle("download lizard image OFFLINE", for: .normal)
        btn.backgroundColor = .blue
        btn.addTarget(self, action: #selector(downloadLizardAction), for: .touchUpInside)
        return btn
    }()

    let imageView : UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFill
        return imageView
    }()

    // I make sure my internet is set to OFF so that it forces this to be read from cache...
    @objc func downloadLizardAction() {
        downloadImage(from: lizardURLString, from: defaultSession)
    }
    let lizardURLString = "https://upload.wikimedia.org/wikipedia/commons/e/e0/Large_Scaled_Forest_Lizard.jpg"
    let landscapeURLString = "https://images.pexels.com/photos/414171/pexels-photo-414171.jpeg"        

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(imageView)
        view.addSubview(downloadLizzardbutton)
        imageView.pinToAllEdges(of: view)

        downloadImage(from: landscapeURLString, from: defaultSession)
    }
    private func downloadImage(from urlString: String, from session : URLSession){
        guard let url = URL(string: urlString) else{
            fatalError("bad String we got!")
        }

        let urlRequest = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 15)
        print("url.hashValue: \(urlRequest.hashValue)")

        let task = session.dataTask(with: urlRequest) { [weak self] (data, response, error) in

            guard error == nil else {
                print(error)
                return
            }
            guard let httpResponse = response as? HTTPURLResponse,
                (200...299).contains(httpResponse.statusCode) else {
                    print("response NOT 2xx: \(response)")
                    return
            }

            for header in httpResponse.allHeaderFields{
                if let key = header.key as? String, key == "Cache-Control"{
                    print("found Cache-Control: \(httpResponse.allHeaderFields["Cache-Control"])")
                }
            }

            if let data = data,
                let image = UIImage(data: data){
                let lizardURL = URL(string: self!.lizardURLString)
                let lizardURLRequest = URLRequest(url: lizardURL!)

                let landscapeCachedURLPResponse : CachedURLResponse = CachedURLResponse(response: response!, data: data, userInfo:nil, storagePolicy: .allowed)
                print("before storing into cache: \(String(describing: session.configuration.urlCache?.cachedResponse(for: lizardURLRequest)))")

                session.configuration.urlCache?.storeCachedResponse(landscapeCachedURLPResponse, for: lizardURLRequest)    

                print("after storing into cache: \(String(describing: session.configuration.urlCache?.cachedResponse(for: lizardURLRequest)))")
                print("lizardRequest.hashValue: \(lizardURLRequest.hashValue)")

                DispatchQueue.main.async {
                    self?.imageView.image = image
                }
            }
        }
        task.resume()
    }        
}


extension UIView{

    func pinToAllEdges(of view: UIView){
        let leading = leadingAnchor.constraint(equalTo: view.leadingAnchor)
        let top = topAnchor.constraint(equalTo: view.topAnchor)
        let trailing = trailingAnchor.constraint(equalTo: view.trailingAnchor)
        let bottom = bottomAnchor.constraint(equalTo: view.bottomAnchor)

        NSLayoutConstraint.activate([leading, top, trailing, bottom])
    }
}
oisas que já validei:MinhaslandscapeURLString tem umcache-control cabeçalho com ummax-age do31536000E s é uma nova instalação, entãoante armazenando no cache, meucachedResponse para lizardURLString énil. Masdepois d armazenando, não é maisnil. Como resultado, concluo que estou armazenando com êxito algo no cache! Também suspeito que o URLCache considere o URLRequest como a chave. Então imprimi o hashValue do meulizardURLString. É o mesmo que a chave que guardei. Combinando isso com o ponto acima, concluí que a chave exata existe no cache! Também posso ver que, quando o armazeno no meu cache, meucurrentMemoryUsage aumenta.Como estou testando e o que estou vendo: Acabei de baixar a imagem da paisagem. Desligue minha internet Clique no botão para baixar a imagem do lagart

Obviamente está offline. Espero que ele use do cache, mas não. Tudo o que recebo é um tempo limite!

Eu também tentei mudar ocachePolicy parareturnCacheDataElseLoad, mas isso também não ajud

EDIT1:

Eu também tentei fazer o que David disse e fez:

let landscapeHTTPResponse : HTTPURLResponse = HTTPURLResponse(url: self!.lizardURL, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: (httpResponse.allHeaderFields as! [String : String]))!
let landscapedCachedURLPResponse : CachedURLResponse = CachedURLResponse(response: landscapeHTTPResponse, data: data, userInfo:nil, storagePolicy: .allowed)

e os @ armazenadlandscapedCachedURLPResponse no cache. Isso também não funcionou. Também atinge o tempo limite - nem sempre é possível olhar para o cach

EDIT2:

Então fiz alguns progressos. Ou talvez deu um passo atrás e um passo adiant

Tentei ver se consigo armazenar a resposta para omesm URL e veja se consigo recuperar a resposta depois de esvaziar meu cache. Não consegui.

Eu estava criando minha resposta em cache assim:

let cachedResponse = CachedURLResponse(response: response!, data: data, userInfo:nil, storagePolicy: .allowed)

ou assim:

let cachedResponse = CachedURLResponse(response: response!, data: data)

O que fez essa parte funcionar?:

let cachedResponseFromCache = session.configuration.urlCache?.cachedResponse(for: self!.landscapeURLRequest)
self._cachedResponse = cachedResponseFromCache

Então eu

liberou o cache desligou a internet tentou fazer o download da imagem, mas não teve sucesso, o que é bom. É o comportamento esperadostoredcachedResponseFromCache propriedade no cache. foi capaz de recuperar do cache!

Não tenho certeza de qual é a diferença entre retirar o próprio cache e criar o cache a partir deResponse + Data.

Isso é importante porque eu estava começando a questionar se ainda há alguma forma deugs internos no URLCache. Isso me deu motivos para acreditar queposs estar trabalhando como esperad

Agora eu sei o processo de armazenamento em cache funciona. Eu sei que meu URLResponse é bom. Eu só preciso trabalhar no mapeamento do URLRequest

EDIT3:

Buy Kogus sugeriu que meus URLs precisam ser da mesma fonte. Então, depois que baixei o bearImage que ele mencionou, minha lagartoImage estava chegando. VOILA!

Como nota de depuração muito importante que eu aprendi: mesmo que você esteja obtendo sucesso em alguma parte (que estava armazenando a imagem da paisagem em si) do problema, a alteração de variáveis (aqui a alteração do URL inicial) sempre pode alterar todos os resultados dos testes.

Ele suspeitava que era porque oServer no cabeçalho compartilhado e isso é importante para procurar o cachedRespons

Eu refutei essa afirmação dizendo que meu lizardURLRequest é feito quando está online, então não há nada para comparar com ele, mas funciona! Portanto, a próxima idéia era que isso pudesse ter algo a ver com parte do URL, como se fosse o primeiro segmento ou algo assim.

Então eu fui e alterei o lizardURL de:

https: //upload.wikimedia.org/wikipedia/commons/e/e0/Large_Scaled_Forest_Lizard.jp

para algo como:https: //skdhfsupload.qwiklkjlkjimedia.com/qwikipehkjdia/eeeeeecommons/sdalfjkdse/aldskfjae0/extraParam/anotherextraparam/asasdLarge_Scaled_Forest_Lizard.jpe

Adicionei caracteres idiotas no URL. Eu também adicionei segmentos extras nele. Mudei o tipo de arquivo no final.

Ainda estava funcionando. Portanto, a única coisa que posso concluir é que algo dos cabeçalhos está fazendo a tomada de decisã

Os cabeçalhos para o meu landscapeURL são (o cache de outro URL não funciona para isso)

Content-Length : 997361
x-cache : HIT, MISS
cf-ray : 472793e93ce39574-IAD
x-served-by : cache-lax8621-LAX, cache-iad2132-IAD
cf-cache-status : HIT
Last-Modified : Sun, 14 Oct 2018 2:10:05 GMT
Accept-Ranges : bytes
Vary : Accept-Encoding
x-content-type-options : nosniff
Content-Type : image/jpeg
expect-ct : max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Set-Cookie : __cfduid=d5f5fd59ce5ff9ac86e42f8c008708ae61541004176; expires=Thu, 31-Oct-19 16:42:56 GMT; path=/; domain=.pexels.com; HttpOnly
Expires : Thu, 31 Oct 2019 16:42:56 GMT
Server : cloudflare
Cache-Control : public, max-age=31536000
Date : Wed, 31 Oct 2018 16:42:56 GMT

Os cabeçalhos para o meu BearURL são (o cache de outro URL funciona para isso)

Date : Wed, 31 Oct 2018 16:46:38 GMT
Content-Length : 215104
x-client-ip : 2001:558:1400:4e:808c:2738:43e:36f5
access-control-expose-headers : Age, Date, Content-Length, Content-Range, X-Content-Duration, X-Cache, X-Varnish
x-cache : cp1076 miss, cp1088 hit/21
Age : 27646
Etag : 00e21950bf432476c91b811bb685b6af
Strict-Transport-Security : max-age=106384710; includeSubDomains; preload
x-analytics : https=1;nocookies=1
Accept-Ranges : bytes
x-object-meta-sha1base36 : 42tq5grg9rq1ydmqd4z5hmmqj6h2309
x-varnish : 48388488, 503119619 458396839
x-cache-status : hit-front
Content-Type : image/jpeg
x-trans-id : tx08ed43bbcc1946269a9a3-005bd97070
Last-Modified : Fri, 04 Oct 2013 23:30:08 GMT
Access-Control-Allow-Origin : *
timing-allow-origin : *
x-timestamp : 1380929407.39127
Via : 1.1 varnish (Varnish/5.1), 1.1 varnish (Varnish/5.1)
Nota importante

Para o BearURL, armazenamento em cache para o BearURL lizardURL ou qualquer outro URL funciona. Para o landscapeURL, o cache funciona apenas para o próprio landscapeURL. Não funciona para nenhumde outro URL.

Então, o estado atual da pergunta é: O que cabeçalhos precisa ser incluído para que isso funcione?

questionAnswers(3)

yourAnswerToTheQuestion