使用 Alamofire 响应填充表视图
Posted
技术标签:
【中文标题】使用 Alamofire 响应填充表视图【英文标题】:Populating table view with Alamofire response 【发布时间】: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
【问题讨论】:
【参考方案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
【讨论】:
以上是关于使用 Alamofire 响应填充表视图的主要内容,如果未能解决你的问题,请参考以下文章
使用 SwiftJSON 将 Alamofire 结果 JSON 加载到表视图中