【问题标题】:Populating table view with Alamofire response使用 Alamofire 响应填充表视图
【发布时间】:2016-06-20 20:35:08
【问题描述】:

我正在尝试使用 Alamofire 获得的响应填充我的 UITableView。 JSON 的 URL 是 https://api.themoviedb.org/3/movie/now_playing?api_key=a07e22bc18f5cb106bfe4cc1f83ad8ed。我只需要这个 JSON 中的 response.result.value["results"] 字典数组。 我没有问题,但是当我尝试在 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
}

【问题讨论】:

    标签: ios swift alamofire


    【解决方案1】:

    Jack 说您的行 print("Entries2: \(self.entries)") 为空是正确的,因为它是在发送 Alamofire 请求后立即执行的。
    将您的 self.entries 分配放在您的 dispatch_async 中应该不会有什么不同,但值得一试。

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

    你在哪里打电话retrieveRecentEntries()?


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

    虽然使用NSDictionary 会起作用,但它来自Objective-C. 而不是[NSDictionary],我建议使用更“快速”的方法并使用[String : AnyObject].

    还有很多情况下,你隐含的unwrapping 你的optionals。如果您知道这些值永远不会是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 解包值。只要这些值中的任何一个为零,您的应用就会崩溃。如果您还不熟悉它,我会checkout Swift 的guard statement。

    【讨论】:

    • 嘿,尽管它没有解决我的问题,但感谢guard,我发现它非常有益,而不是在这里使用if ... else ...。
    • 不客气!我很高兴您能够解决您的问题。 ?
    【解决方案2】:

    当你打印 Entries2 时,数组是空的,因为该代码是在 alamofire 请求发送后立即执行的,所以还没有收到响应。

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

    self.entries = (response.result.value!["results"] as? [NSDictionary])!
    

    到 dispatch_async 块内。

    【讨论】:

      【解决方案3】:

      这个问题都是关于编码的。我将参数编码为 .JSON,这对于 .GET 函数不是必需的。应该是

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

      或

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

      因为使用 URL 进行编码是默认设置。代码是正确的,是的,我使用guard 安全地解包接收到的数据。

      【讨论】:

        【解决方案4】:

        顺便说一句,在 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 
        }
        

        【讨论】:

          猜你喜欢
          • 2016-02-14
          • 2018-12-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-19
          • 2017-04-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多