Wes*_*Cho 4 json uitableview ios swift alamofire
我试图将搜索结果显示在tableView上。我相信我已经正确解析了JSON,唯一的问题是结果不会显示在tableView上。
这是代码:
var searchText : String! {
didSet {
getSearchResults(searchText)
}
}
var itemsArray = [[String:AnyObject]]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.reloadData()
}
// MARK: - Get data
func getSearchResults(text: String) {
if let excapedText = text.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) {
Alamofire.request(.GET, "https://api.duckduckgo.com/?q=\(excapedText)&format=json")
.responseJSON { response in
guard response.result.error == nil else {
// got an error in getting the data, need to handle it
print("error \(response.result.error!)")
return
}
let items = JSON(response.result.value!)
if let relatedTopics = items["RelatedTopics"].arrayObject {
self.itemsArray = relatedTopics as! [[String:AnyObject]]
}
if self.itemsArray.count > 0 {
self.tableView.reloadData()
}
}
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6 // itemsArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SearchResultCell", forIndexPath: indexPath) as! SearchResultCell
if itemsArray.count > 0 {
var dict = itemsArray[indexPath.row]
cell.resultLabel?.text = dict["Text"] as? String
} else {
print("Results not loaded yet")
}
return cell
}
Run Code Online (Sandbox Code Playgroud)
如果我有一个静态的API请求,我认为这段代码会起作用,因为我可以获取viewDidLoad并避免很多.isEmpty检查。
当我运行程序时,我得到6 Results not loaded yet(来自printin cellForRowAtIndexPath)。
当完成处理程序被调用时response in,它下降到self.items.count > 3(通过)然后命中self.tableView.reloadData(),它什么也没做(我在上面设置了一个断点来检查)。
我的代码有什么问题?
编辑
if self.itemsArray.count > 0 {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
}
Run Code Online (Sandbox Code Playgroud)
尝试了这个,但是tableView仍然没有重新加载,即使在调用alamofire处理程序之前重新加载了6次...
这是一件奇怪的事情,很明显在hander被调用之前,我itemsArray.count将为0,所以这就是我得到的原因Results not loaded yet。我弄清楚了为什么重复六遍。我将其设置为numberOfRowsInSection...所以@Rob,我无法检查,dict["Text"]或者cell.resultLabel?.text因为它们从未被调用。不过,“文本”是正确的,这是指向JSON的链接:http : //api.duckduckgo.com/? q= DuckDuckGo& format=json& pretty=1
另外,我确实将标签链接到自定义单元格类 SearchResultCell
最后,我得到了可见的结果。
两个问题。
一个问题是prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let searchResultTVC = SearchResultsTVC()
searchResultTVC.searchText = searchField.text
}
Run Code Online (Sandbox Code Playgroud)
那不是使用已经实例化的“目标”视图控制器,而是创建第二个SearchResultsTVC,设置第二个,searchText然后使其超出范围并被释放,从而丢失搜索文本。
相反,您想要:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let searchResultTVC = segue.destination as? SearchResultsTVC {
searchResultTVC.searchText = searchField.text
}
}
Run Code Online (Sandbox Code Playgroud)您不应该依赖didSet目标视图控制器来触发搜索,因为该属性是在实例化表视图之前由源视图控制器设置的。在加载视图(viewDidLoad)之前,您不希望启动搜索。
我会建议更换didSet逻辑,只是执行搜索viewDidLoad的那个SearchResultsTVC。
我的原始答案如下,讨论原始问题中提供的代码。
-
我使用了最初在问题中提供的代码,并且工作正常。我个人可能会进一步简化它:
消除中的硬编码“ 6” numberOfRowsInSection,因为这将在控制台中给您带来误报错误;
转义的百分比不太正确(某些字符将滑过,未转义);与其专注于自己的正确方法,不如让Alamofire使用parameters;
我个人会消除SwiftyJSON,因为它不提供任何价值... Alamofire已经为我们完成了JSON解析。
无论如何,我的简化格式如下:
class ViewController: UITableViewController {
var searchText : String!
override func viewDidLoad() {
super.viewDidLoad()
getSearchResults("DuckDuckGo")
}
var itemsArray: [[String:AnyObject]]?
func getSearchResults(text: String) {
let parameters = ["q": text, "format" : "json"]
Alamofire.request("https://api.duckduckgo.com/", parameters: parameters)
.responseJSON { response in
guard response.result.error == nil else {
print("error \(response.result.error!)")
return
}
self.itemsArray = response.result.value?["RelatedTopics"] as? [[String:AnyObject]]
self.tableView.reloadData()
}
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemsArray?.count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SearchResultCell", for: indexPath) as! SearchResultCell
let dict = itemsArray?[indexPath.row]
cell.resultLabel?.text = dict?["Text"] as? String
return cell
}
}
Run Code Online (Sandbox Code Playgroud)
当我这样做时,我得到以下信息:
问题必须放在其他地方。也许在情节提要中。也许是在searchText您未与我们共享的更新代码中(这会通过触发查询didSet)。很难说。但这在您提供的代码片段中似乎不是问题。
但是,在进行调试时,请确保不要在第一次调用表视图委托方法时和第二次调用时(由responseJSON块触发)合并它们。通过消除中的硬编码“ 6” numberOfRowsInSection,可以减少一些误报。
| 归档时间: |
|
| 查看次数: |
2396 次 |
| 最近记录: |