使用Alamofire和SwiftyJSON检索一些JSON是微不足道的:
给出JSON,例如
{
"results": [
{
"id": "123",
"name": "Bob"
},
{
"id": "456",
"name": "Sally"
}
}
此功能可以使用:
func loadSomeJSONData() {
Alamofire.request(.GET, "http://example.com/json/")
.responseJSON { (_, _, data, _) in
let json = JSON(data!)
if let firstName = json["results"][0]["name"].string {
println("first name: \(firstName)") // firstName will equal "Bob"
}
}
}
一切都很好。当我需要从分页API加载JSON时,即从多次调用API端点收集数据时,我的问题出现了,其中JSON看起来更像:
{
"currentPage": "1",
"totalPages": "6"
"results": [
{
"id": "123",
"name": "Bob"
},
{
"id": "456",
"name": "Sally"
}
]
}
然后下一个块看起来像:
{
"currentPage": "2",
"totalPages": "6"
"results": [
{
"id": "789",
"name": "Fred"
},
{
"id": "012",
"name": "Jane"
}
]
}
在这种情况下,我可以递归调用函数来收集所有“页面”,但我不确定如何正确地将所有JSON片段放在一起:
func loadSomeJSONDataFromPagedEndPoint(page : Int = 1) {
Alamofire.request(.GET, "http://example.com/json/" + page)
.responseJSON { (_, _, data, _) in
let json = JSON(data!)
if let totalPages = json["totalPages"].description.toInt() {
if let currentPage = json["currentPage"].description.toInt() {
let pageOfJSON = json["results"]
// add pageOfJSON to allJSON somehow??
if currentPage < totalPages {
self.loadSomeJSONDataFromPagedEndPoint(page: currentPage+1)
} else {
// done loading all JSON pages
}
}
}
var allJSON
loadSomeJSONDataFromPagedEndPoint()
我想要发生的是将每个JSON响应的“结果”部分最终收集到一个对象数组中({ "id": "123", "name": "Bob"}
个对象)
奖金问题:我不确定为什么我需要json["totalPages"].description.toInt()
才能获得totalPages
的价值,必须有更好的方法吗?
答案 0 :(得分:15)
这里有几个问题,所以让我们一次拿一个。
如果您为每个页面调用获得有效的JSON,或者您是否需要完全放置它们来完成JSON,我无法从您的帖子中看出来。让我们来看看这两种情况。
你已经非常接近了,你只需要稍微调整你的JSON解析并存储结果。这就是它的样子。
class PagedDownloader {
var pagedResults = [AnyObject]()
func loadSomeJSONDataFromPagedEndPoint(page: Int) {
let request = Alamofire.request(.GET, "http://example.com/json/\(page)")
request.responseJSON { [weak self] _, _, jsonData, _ in
if let strongSelf = self {
let json = JSON(jsonData!)
let totalPages = json["totalPages"].stringValue.toInt()!
let currentPage = json["currentPage"].stringValue.toInt()!
let results = json["results"].arrayObject!
strongSelf.pagedResults += results
if currentPage < totalPages {
strongSelf.loadSomeJSONDataFromPagedEndPoint(currentPage + 1)
} else {
strongSelf.parsePagedResults()
}
}
}
}
func parsePagedResults() {
let json = JSON(pagedResults)
println(json)
}
}
您似乎了解SwiftyJSON的方式,因此我将让您处理parsePagedResults
实施。
分页JSON
首先,你不能解析部分JSON,它只是不起作用。 NSJSONSerialization
将失败。这意味着您无法将responseJSON
序列化程序与分页JSON一起使用,因为data
始终为nil,error
始终为json序列化错误。简而言之,您需要缓存所有数据,直到它是有效的JSON,然后您才能解析。
存储分页JSON
如果您要存储它,这就是一个简单的例子,如果没有Alamofire的话,它可能就像这样。
class Pager {
let page1 = "{\"currentPage\":\"1\",\"totalPages\":\"3\",\"results\":[{\"id\":\"123\",\"name\":\"Bob\"},"
let page2 = "{\"id\":\"456\",\"name\":\"Sally\"},{\"id\":\"234\",\"name\":\"Christian\"},"
let page3 = "{\"id\":\"567\",\"name\":\"Jerry\"},{\"id\":\"345\",\"name\":\"John\"}]}"
let pages: [String]
let jsonData: NSMutableData
init() {
self.pages = [page1, page2, page3]
self.jsonData = NSMutableData()
}
func downloadPages() {
for (index, page) in enumerate(pages) {
jsonData.appendData(page.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!)
}
let json = JSON(data: jsonData)
println(json)
if let totalPages = json["totalPages"].string?.toInt() {
println("Total Pages Value: \(totalPages)")
}
}
}
您的奖金问题会在该代码块的末尾回答。您不希望使用SwiftyJSON中的
description
,而是使用string
可选的强制转换,然后使用toInt
方法中的可选链。
使用Alamofire进行分页和存储
现在您已经有了一个如何将JSON页面写入数据块的简单示例,让我们看一下如何在Alamofire中使用response
序列化器来使用相同的方法。
class Downloader {
var jsonData = NSMutableData()
var totalPagesDownloaded = 0
let totalPagesToDownload = 6
func loadSomeJSONDataFromPagedEndPoint() {
for page in 1...self.totalPagesToDownload {
let request = Alamofire.request(.GET, "http://example.com/json/\(page)")
request.response { [weak self] _, _, data, _ in
if let strongSelf = self {
strongSelf.jsonData.appendData(data as NSData)
++strongSelf.totalPagesDownloaded
if strongSelf.totalPagesDownloaded == strongSelf.totalPagesToDownload {
strongSelf.parseJSONData()
}
}
}
}
}
func parseJSONData() {
let json = JSON(data: jsonData)
println(json)
}
}
使用SwiftyJSON解析生成的JSON
在parseJSONData
函数中,只需使用SwiftyJSON的所有强大功能来解析所需的值。
我很确定这涵盖了所有可能的用例和问题。希望有所帮助!