URLresponse no se recupera después de almacenar en caché usando storeCachedResponse

Go

Estoy intentando inyectar datos / respuestas de URLRequest enotr URLRequest en mi caché.

Prepara

Esto es solo un código de muestra. Está listo para ser arrojado a un proyecto.

o que intento hacer es usar la respuesta + datos recuperados de milandscapeURLString solicitud de red ... almacenar en el caché de mi sesiónfor my lizardURLString solicitud

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])
    }
}
Cosas que ya he validado:MilandscapeURLString tiene uncache-control encabezado con unmax-age de31536000S es una instalación nueva, luegoantes d almacenando en el caché, micachedResponse for lizardURLString esnil. Perodespué almacenamiento, ya no esnil. ¡Como resultado, concluyo que estoy almacenando con éxito algo en el caché! También sospecho que URLCache considera la URLRequest como la clave. Así que imprimí el hashValue de milizardURLString. Es la misma clave que he almacenado. ¡Combinando eso con el punto anterior, llegué a la conclusión de que la clave exacta existe en el caché! También puedo ver que cuando lo guardo en mi caché, micurrentMemoryUsage aumenta.Cómo estoy probando y lo que estoy viendo: Acabo de descargar la imagen del paisaje. Apagar mi internetHaga clic en el botón para descargar la imagen del lagarto.

Obviamente está fuera de línea. Espero que lo use del caché pero no lo hace. ¡Todo lo que obtengo es un tiempo muerto!

Traté de cambiar lacachePolicy areturnCacheDataElseLoad, pero eso tampoco ayudó a

EDIT1:

Traté de hacer lo que David dijo y hacer:

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)

y el @ almacenalandscapedCachedURLPResponse en el caché. Eso tampoco funcionó. También se agota el tiempo de espera: no todos miran al caché.

EDIT2:

Así que hice algunos progresos. O tal vez dio un paso atrás y un paso adelante.

ntenté ver si puedo almacenar la respuesta para lamism URL y ver si puedo recuperar la respuesta después de vaciar mi caché. No pude.

Estaba creando mi respuesta en caché de esta manera:

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

o así:

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

¿Qué tiene esta parte para trabajar?:

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

Entonces yo

arrojó el caché apagado de internet intenté descargar la imagen, pero no tuve éxito, lo cual es bueno. Es el comportamiento esperadostoredcachedResponseFromCache propiedad en el caché.@ fue capaz de recuperar del caché!

No estoy seguro de cuál es la diferencia entre arrancar del caché y crear el caché desdeResponse + Data.

Esto es importante porque estaba empezando a preguntarme si todavía hay alguna forma de errores internos en URLCache. Esto me ha dado razones para creer quemay estar trabajando como se esperaba.

Ahora sé que el proceso de almacenamiento en caché funciona. Sé que mi URLResponse es buena. Solo necesito trabajar a través del mapeo de URLRequest

EDIT3:

Guy Kogus sugirió que mis URL deben ser de la misma fuente. Entonces, una vez que descargué el BearImage que mencionó, mi lizardImage estaba llegando. VOILA!

Como nota de depuración muy importante que aprendí: incluso si está obteniendo éxito en alguna parte (que estaba almacenando en caché la imagen del paisaje) del problema, cambiar las variables (aquí cambiar la URL inicial) siempre puede cambiar los resultados completos de las pruebas. @

l sospechaba que era porque elServer en el encabezado compartido y eso es importante para buscar la respuesta en caché.

Refuté esa afirmación diciendo que mi lizardURLRequest se realiza cuando está en línea, por lo que no hay nada con lo que comparar, ¡pero funciona! Entonces, la siguiente idea fue que podría tener algo que ver con alguna parte de la URL, como su primer segmento o algo así.

ntonces, fui y modifiqué el lizardURL de:

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

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

Agregué caracteres tontos en la URL. También agregué segmentos adicionales. Cambié el tipo de archivo al final.

Todavía estaba funcionando. Entonces, lo único que puedo concluir es que algo de los Encabezados está haciendo la toma de decisiones.

Los encabezados de mi landscapeURL son (el almacenamiento en caché de otra URL no funciona para esto)

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

Los encabezados de mi BearURL son (el almacenamiento en caché de otra URL funciona para esto)

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 el BearURL, almacenamiento en caché para el BearURL lizardURL o cualquier otra URL funciona. Para landscapeURL, el almacenamiento en caché solo funciona para el propio landscapeURL. No funciona para ningunaotr URL.

Así que el estado actual de la pregunta es: ¿Qué encabezados ¿necesita ser incluido para que esto funcione?