簡體   English   中英

Swift:將Alamofire和SwiftyJSON與分頁JSON API一起使用

[英]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,我無法從您的帖子中看出來。 讓我們來看看這兩種情況。

選項1 - 每個頁面的有效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實現。

選項2 - 必須組裝頁面才能創建有效的JSON

分頁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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM