swiftyjson example ios json swift http caching alamofire

example - Sincronización de datos JSON remotos con almacenamiento en caché local en iOS Swift



swiftyjson alamofire swift 4 (3)

A continuación se muestra el código que utilicé para almacenar en caché mis solicitudes usando Alamofire y SwiftyJSON.

func getPlaces(){ //Request with caching policy let request = NSMutableURLRequest(URL: NSURL(string: baseUrl + "/places")!, cachePolicy: .ReturnCacheDataElseLoad, timeoutInterval: 20) Alamofire.request(request) .responseJSON { (response) in let cachedURLResponse = NSCachedURLResponse(response: response.response!, data: (response.data! as NSData), userInfo: nil, storagePolicy: .Allowed) NSURLCache.sharedURLCache().storeCachedResponse(cachedURLResponse, forRequest: response.request!) guard response.result.error == nil else { // got an error in getting the data, need to handle it print("error calling GET on /places") print(response.result.error!) return } let swiftyJsonVar = JSON(data: cachedURLResponse.data) if let resData = swiftyJsonVar["places"].arrayObject { // handle the results as JSON, without a bunch of nested if loops self.places = resData //print(self.places) } if self.places.count > 0 { self.tableView.reloadData() } } }

Estoy tratando de encontrar la solución para el procesamiento simple de todos los pasos necesarios para datos JSON remotos que consumen solo lectura en dispositivos iOS. Significa obtener datos JSON remotos, almacenarlos en la memoria caché local en un dispositivo iOS para uso sin conexión, actualizar la memoria caché y analizar datos JSON. Creo que hoy en día es un requisito muy común para todas las aplicaciones móviles.

Sé que es posible descargar manualmente el archivo JSON remoto, almacenarlo en una base de datos local o en un archivo en un dispositivo iOS y, cuando la red no esté disponible, recuperarlo del almacenamiento local, de lo contrario, descargarlo de la red. Lo hago manualmente ahora. :) Pero hay muchos pasos que la esperanza es posible mediante el uso de frameworks / bibliotecas, ¿no?

¡Así que probé el framework HanekeSwift que hace casi todo lo que necesito pero solo almacena en caché JSON remoto (e imágenes) pero no actualiza el caché! lo cual no es útil para mi También sé que existe Alamofire y SwiftyJSON, pero no tengo ninguna experiencia con ellos.

¿Tienes alguna experiencia en cómo hacer eso?

Resumen

  • bibliotecas o marcos para el soporte de iOS8 en Swift
  • descargue JSON remoto y almacene en la memoria caché local
  • posibilidad de actualizar el caché local desde su origen
  • buen bono es fácil análisis JSON


Esta es una versión de Swift 3 basada en la respuesta de Charl (usando SwiftyJSON y Alamofire ):

func getData(){ let query_url = "http://YOUR-URL-HERE" // escape your URL let urlAddressEscaped = query_url.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed) //Request with caching policy let request = URLRequest(url: URL(string: urlAddressEscaped!)!, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 20) Alamofire.request(request) .responseJSON { (response) in let cachedURLResponse = CachedURLResponse(response: response.response!, data: (response.data! as NSData) as Data, userInfo: nil, storagePolicy: .allowed) URLCache.shared.storeCachedResponse(cachedURLResponse, for: response.request!) guard response.result.error == nil else { // got an error in getting the data, need to handle it print("error fetching data from url") print(response.result.error!) return } let json = JSON(data: cachedURLResponse.data) // SwiftyJSON print(json) // Test if it works // do whatever you want with your data here } }


Gran pregunta!

Puede lograr esto absolutamente con una combinación de Alamofire y SwiftyJSON. Lo que recomendaría es una combinación de varias cosas para que esto sea lo más fácil posible.

Creo que tienes dos enfoques para buscar el JSON.

  1. Obtenga los datos JSON en memoria y use una política de caché
  2. Descargue los datos JSON al disco directamente a su caché local

Opción 1

// Create a shared URL cache let memoryCapacity = 500 * 1024 * 1024; // 500 MB let diskCapacity = 500 * 1024 * 1024; // 500 MB let cache = NSURLCache(memoryCapacity: memoryCapacity, diskCapacity: diskCapacity, diskPath: "shared_cache") // Create a custom configuration let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() var defaultHeaders = Alamofire.Manager.sharedInstance.session.configuration.HTTPAdditionalHeaders configuration.HTTPAdditionalHeaders = defaultHeaders configuration.requestCachePolicy = .UseProtocolCachePolicy // this is the default configuration.URLCache = cache // Create your own manager instance that uses your custom configuration let manager = Alamofire.Manager(configuration: configuration) // Make your request with your custom manager that is caching your requests by default manager.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"], encoding: .URL) .response { (request, response, data, error) in println(request) println(response) println(error) // Now parse the data using SwiftyJSON // This will come from your custom cache if it is not expired, // and from the network if it is expired }

opcion 2

let URL = NSURL(string: "/whereever/your/local/cache/lives")! let downloadRequest = Alamofire.download(.GET, "http://httpbin.org/get") { (_, _) -> NSURL in return URL } downloadRequest.response { request, response, _, error in // Read data into memory from local cache file now in URL }

La opción 1 ciertamente aprovecha la mayor cantidad de almacenamiento en caché compatible con Apple. Creo que con lo que está tratando de hacer, debería poder aprovechar NSURLSessionConfiguration y una política de caché particular para lograr lo que está buscando hacer.

La opción 2 requerirá una cantidad de trabajo mucho mayor, y será un sistema un poco extraño si aprovecha una política de caché que realmente almacena en caché los datos en el disco. Las descargas terminarían copiando datos ya almacenados en caché. Así es como sería el flujo si su solicitud existiera en su caché de URL personalizada.

  1. Hacer solicitud de descarga
  2. La solicitud se almacena en caché, por lo que los datos en caché se cargan en NSInputStream
  3. Los datos se escriben en la URL proporcionada a través de NSOutputStream
  4. Se llama al serializador de respuesta donde carga los datos nuevamente en la memoria
  5. Luego, los datos se analizan usando SwiftyJSON en objetos modelo

Esto es bastante derrochador a menos que esté descargando archivos muy grandes. Potencialmente podría encontrarse con problemas de memoria si carga todos los datos de la solicitud en la memoria.

La copia de los datos en caché a la URL proporcionada probablemente se implementará a través de NSInputStream y NSOutputStream. Todo esto es manejado internamente por Apple por el marco de la Fundación. Esta debería ser una forma muy eficiente en la memoria para mover los datos. La desventaja es que necesita copiar todo el conjunto de datos antes de poder acceder a él.

NSURLCache

Otra cosa que puede ser muy útil aquí para usted es la capacidad de obtener una respuesta en caché directamente desde su NSURLCache . Eche un vistazo al método cachedReponseForRequest: que se puede encontrar here .

SwiftyJSON

El último paso es analizar los datos JSON en objetos modelo. SwiftyJSON hace esto muy fácil. Si está utilizando la Opción 1 de arriba, puede usar el serializador de respuesta personalizado en el Alamofire-SwiftyJSON . Eso se parecería a lo siguiente:

Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"]) .responseSwiftyJSON { (request, response, json, error) in println(json) println(error) }

Ahora, si utilizó la Opción 2 , deberá cargar los datos del disco, luego inicializar un objeto SwiftyJSON y comenzar a analizar lo que se vería así:

let data = NSData(contentsOfFile: URL.path)! let json = JSON(data: data)

Eso debería abarcar todas las herramientas que necesita para lograr lo que intenta. Sin duda, la forma en que diseñe la solución exacta depende de usted, ya que hay muchas formas posibles de hacerlo.