用Alamofire响应填充表视图

时间:2016-06-20 20:35:08

标签: ios swift alamofire

我正在尝试使用Alamofire获得的响应来填充我的UITableView。 JSON的网址是https://api.themoviedb.org/3/movie/now_playing?api_key=a07e22bc18f5cb106bfe4cc1f83ad8ed。我只需要来自这个JSON的response.result.value ["结果"]字典数组。 我没有问题,但是当我尝试在Alamofire之外打印时,请求它是空的,并且由于单元格数为0,因此我的单元格无法填充此数据。 我在主线程中尝试了tableView.reloadData(),就像这里Populating Table Cells With Alamofire Data所说的那样,但这没有给出积极的结果。你觉得我做错了什么?我委托了表视图,并更新了框架,一切都应该正常工作。

以下是代码:

func retrieveRecentEntries() {
    let url = "https://api.themoviedb.org/3/movie/now_playing?api_key=a07e22bc18f5cb106bfe4cc1f83ad8ed"

    Alamofire.request(.GET, url, parameters: [:], encoding: .JSON, headers: [:]).responseJSON { (response) in
        self.entries = (response.result.value!["results"] as? [NSDictionary])!

        dispatch_async(dispatch_get_main_queue()) {
            print("OO")
            print("Entries1: \(self.entries)")//giving JSON


            self.tableView.reloadData()
        }
    }

    print("Entries2: \(self.entries)")//empty

}

UITableView委托方法:

   func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    //Sort entries by date and return amount of entries for each date section
    return entries.count ?? 0
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("entryCell", forIndexPath: indexPath) as! EntryCell

    //Populate each indexPath.row with one entry
    let entryDict = entries[indexPath.row]

    let dateString = entryDict["release_date"] as! String
    formatter.dateFormat = "yyyy-MM-dd"

    let dateDate = formatter.dateFromString(dateString)
    formatter.dateFormat = "MMMM d, yyyy"

    let dateStr = formatter.stringFromDate(dateDate!)

    //Store entry details to show them as labels
    let projectName = entryDict["title"] as! String
    let description = entryDict["overview"] as! String
    let task = entryDict["original_title"] as! String
    let hours = entryDict["vote_average"] as! Double

    //Show cell labels
    cell.projectNameLabel.text = projectName
    cell.dateLabel.text = dateStr
    cell.taskLabel.text = task
    cell.descriptionLabel.text = description
    cell.hoursLabel.text = String(format: "%.2f", hours)

    print("HERE")//this isn't printed
    return cell
}

4 个答案:

答案 0 :(得分:1)

杰克说的是,您的第print("Entries2: \(self.entries)")行是空的,因为它在发送Alamofire请求后立即执行。 将self.entries的作业放在dispatch_async内并不会有所作为,但值得一试。

您提到您已正确设置delegate。你还设置了dataSource吗?

你在哪里打retrieveRecentEntries()

关于他们的价值的一些建议。

虽然使用NSDictionary会有效,但它来自Objective-C.而不是[NSDictionary]我会建议更多" Swifty"接近并使用[String : AnyObject].

在很多情况下,您隐含unwrapping optionals checkout。如果你知道这些值永远不会是nil.,那就好了。但是由于您要解包的值来自服务器,因此最好处理这些值的可能性正在nil.因为如果他们是并且您隐含地打开它们,您的应用程序将崩溃 我建议更新您的代码,使其更安全,并按如下方式进行操作。

func retrieveRecentEntries() {
    let url = "https://api.themoviedb.org/3/movie/now_playing?api_key=a07e22bc18f5cb106bfe4cc1f83ad8ed"

    Alamofire.request(.GET, url, parameters: [:], encoding: .JSON, headers: [:]).responseJSON { (response) in

        guard let validResponse = response.result.value as? [String : AnyObject], validEntries = validResponse["results"] as? [String: AnyObject] else {
            return
        }

        // Now you can assign validEntries to self.entries because you know it is not nil
        self.entries = validEntries

        dispatch_async(dispatch_get_main_queue()) {
            print("OO")
            print("Entries1: \(self.entries)")//giving JSON
            self.tableView.reloadData()
        }
    }
}

我还会更新cellForRowAtIndexPath中您隐含地从entryDict展开值的所有地点。任何时候任何这些值都是零你的应用程序将崩溃。如果您还不熟悉它,我会statement斯威夫特的guard {{3}}。

答案 1 :(得分:0)

当您打印Entries2时,该数组为空,因为该代码在发送alamofire请求后立即执行,因此尚未收到响应。

可能发生的情况是,当您调用reloadData()时,条目不会更新。尝试移动

Foreach

到dispatch_async块内。

答案 2 :(得分:0)

这个问题与编码有关。我将参数编码为.JSON,这对.GET函数来说不是必需的。它应该是

Alamofire.request(.GET, url, parameters: [:], encoding: .URL, headers: [:]).responseJSON { (response) in

Alamofire.request(.GET, url, parameters: [:], headers: [:]).responseJSON { (response) in

带URL的编码是默认设置。代码是正确的,是的,我使用guard来安全地解开接收到的数据。

答案 3 :(得分:0)

顺便说一句,在Alamofire 3(Swift 2.3)中,response.result.value在失败时为零,所以你不能再使用它了:

guard let validResponse = response.result.value as? [String : AnyObject], validEntries = validResponse["results"] as? [String: AnyObject] else {
    return
}

您需要解析数据,因为无论响应是成功还是失败,都会返回数据:

guard let data = response.data,
                    let json = try? NSJSONSerialization.JSONObjectWithData(data, options: []),
                    let responseJSON = json as? [String:AnyObject] else {
    return 
}