[英]Swift: Using Alamofire and SwiftyJSON with a paged JSON API
使用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
的值,必須有更好的方法嗎?
你在這里有幾個問題,所以讓我們一次拿一個。
如果您為每個頁面調用獲得有效的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
轉換,然后將可選鏈轉換為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的所有強大功能來解析您需要的值。
我很確定這涵蓋了所有可能的用例和問題。 希望有所幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.