在iOS Swift中将远程JSON数据同步到本地缓存存储

kol*_*sko 60 caching http ios swift alamofire

我正在尝试找到解决方案,以简单处理iOS设备上只读消耗远程JSON数据的所有必要步骤.这意味着获取远程JSON数据,存储到iOS设备上的本地缓存以供脱机使用,刷新缓存,解析JSON数据.我认为现在所有移动应用都是非常普遍的要求.

我知道可以手动下载远程JSON文件,将其存储到iOS设备上的本地数据库或文件中,当网络不可用时从本地存储中获取它,否则从网上下载.我现在手动完成.:)但是希望通过使用框架/库可以做的许多步骤,不是吗?

所以我尝试了几乎所有我需要的HanekeSwift框架,但它只缓存远程JSON(和图像),但不刷新缓存!这对我没用.我也知道存在Alamofire和SwiftyJSON,但我对它们没有任何经验.

你有任何经验如何做到这一点?

摘要

  • Swift中支持iOS8的库或框架
  • 下载远程JSON并存储到本地缓存
  • 可以从它的原点刷新本地缓存
  • 好的奖金是简单的JSON解析

在此输入图像描述

cno*_*oon 39

好问题!

您可以通过Alamofire和SwiftyJSON的组合来完成此任务.我建议的是将几件事情结合起来,尽可能简化.

我认为你有两种获取JSON的方法.

  1. 在内存中获取JSON数据并使用缓存策略
  2. 将JSON数据直接下载到磁盘到本地缓存

选项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
       }
Run Code Online (Sandbox Code Playgroud)

选项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
}
Run Code Online (Sandbox Code Playgroud)

选项1肯定会利用最大量的Apple支持的缓存.我认为,通过您尝试做的事情,您应该能够利用NSURLSessionConfiguration特定的缓存策略来完成您想要做的事情.

选项2将需要更大量的工作,如果您利用实际缓存磁盘上数据的缓存策略,它将是一个奇怪的系统.下载最终将复制已缓存的数据.如果您的请求存在于自定义URL缓存中,那么这就是流程的样子.

  1. 提出下载请求
  2. 请求被缓存,因此缓存的数据被加载到NSInputStream中
  3. 数据URL通过NSOutputStream 写入提供的数据
  4. 调用响应序列化程序,将数据加载到内存中
  5. 然后使用SwiftyJSON将数据解析为模型对象

除非您下载非常大的文件,否则这非常浪费.如果将所有请求数据加载到内存中,则可能会遇到内存问题.

将缓存数据复制到提供的数据URL很可能是通过NSInputStream和NSOutputStream实现的.这一切都由Apple在Foundation框架内部处理.这应该是一种非常有效的内存移动数据的方法.缺点是您需要先复制整个数据集,然后才能访问它.

NSURLCache

另一件可能对您非常有用的事情是能够直接从您的缓存中获取缓存的响应NSURLCache.看看这里cachedReponseForRequest:可以找到的方法.

SwiftyJSON

最后一步是将JSON数据解析为模型对象.SwiftyJSON让这很容易.如果您使用上面的选项1,那么您可以使用Alamofire-SwiftyJSON中的自定义响应序列化程序.这看起来像下面这样:

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

现在,如果您使用选项2,则需要从磁盘加载数据,然后初始化SwiftyJSON对象并开始解析,如下所示:

let data = NSData(contentsOfFile: URL.path)!
let json = JSON(data: data)
Run Code Online (Sandbox Code Playgroud)

这应该涵盖您应该完成所尝试的所有工具.你如何构建精确的解决方案当然取决于你,因为有很多可能的方法来做到这一点.

  • 在我的应用程序中,我将使用选项1并使用`NSURLCache`.我没有可用的连接时,我想使用缓存的响应.在连接缺失的情况下,是否存在直接使用缓存而不发出请求的方法?谢谢 (2认同)