在iOS版雨燕

问题描述:

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

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

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

你有什么经验该怎么做?

摘要

  • 库或框架在斯威夫特iOS8上的支持
  • 下载远程JSON和存储到本地缓存
  • 可能性刷新本地缓存从它的起源
  • 不错的奖金很容易JSON解析

enter image description here

谢谢! Michal

好问题!

您可以绝对与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 
     } 

选项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 
} 

选项1肯定利用苹果的最大负载量缓存。我认为,通过你想要做的事情,你应该能够利用NSURLSessionConfiguration和一个特定的cache policy来完成你想要做的事情。

选项2将需要更大的工作量,如果您利用实际缓存磁盘上的数据的缓存策略,则会有点奇怪的系统。下载将最终复制已经缓存的数据。如果您的请求存在于您的自定义网址缓存中,则流程如下所示。

  1. 制作下载请求
  2. 请求被装入NSInputStream高速缓存,所以缓存数据
  3. 数据通过NSOutputStream写入提供URL
  4. 响应串被称为在这里装载数据返回到内存
  5. 然后使用SwiftyJSON将数据解析为模型对象

This i除非你正在下载非常大的文件,否则很浪费。如果将所有请求数据加载到内存中,则可能会遇到内存问题。

将高速缓存的数据复制到提供的URL很可能通过NSInputStream和NSOutputStream实现。这一切都是由基金会框架在Apple内部处理的。这应该是移动数据的高效内存方式。缺点是您需要复制整个数据集才能访问它。

NSURLCache

这里可以非常有用的,你是直接从您的NSURLCache获取缓存的响应能力的一两件事。看看cachedReponseForRequest:的方法,可以找到here

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) 
     } 

现在,如果你使用选项2,则需要加载数据从磁盘,然后初始化一个SwiftyJSON对象,并开始分析这将是这个样子:

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

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

+0

感谢您的回答!对我来说唯一可行的解​​决方案是将选项2存储在本地磁盘上。当1.网络连接不可用时,Alamofire究竟做了什么?2.什么时候? ad1 - 从缓存中加载数据(如果可用),ad2 - 刷新缓存中的数据?也许愚蠢的问题,但它是正确的? – kolisko 2015-02-11 19:34:40

+0

如果网络连接不可用,您将在'response'中收到网络错误。如果你有互联网连接,你当然可以添加逻辑来尝试下载数据。至于你的其他问题,我对'NSURLCache'和不同的'NSURLRequestCachePolicy'做了一些大的更新。希望能够让您更好地利用已有的苹果缓存系统的选项。 – cnoon 2015-02-12 06:16:28

+2

在我的应用程序中,我将使用选项1并使用'NSURLCache'。我想在没有可用连接时使用缓存响应。它是否存在一种直接使用缓存的方式,在没有请求的情况下,在连接不存在的情况下?谢谢 – 2016-05-04 14:45:55

下面是我用来缓存使用Alamofire和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() 
      } 
    } 
} 
+0

是否有可能修改缓存的数据以便稍后更新服务器上的数据? – fullMoon 2017-11-08 13:07:09

这是一个基于查尔的回答一个斯威夫特3版本(使用SwiftyJSONAlamofire ):

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 

    } 
} 
+0

通过调用动态(不同的请求url和参数)请求,我得到相同的响应,这是第一次存储在缓存中。任何想法 ? – 2017-03-04 09:24:07

+0

@lenooh。是否有可能使用Alamofire以快速方式存储数据3 – 2017-05-15 06:44:35

+0

@jayaraj&lenooh ..这是我的代码,https://ibb.co/nKKXkk。我怎样才能在swift 3中实现这种离线存储? – 2017-05-15 07:32:04