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
    }
如果我有一个静态的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()
                        })
                    }
尝试了这个,但是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
}
那不是使用已经实例化的“目标”视图控制器,而是创建第二个SearchResultsTVC,设置第二个,searchText然后使其超出范围并被释放,从而丢失搜索文本。
相反,您想要:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let searchResultTVC = segue.destination as? SearchResultsTVC {
        searchResultTVC.searchText = searchField.text
    }
}
您不应该依赖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
    }
}
当我这样做时,我得到以下信息:
问题必须放在其他地方。也许在情节提要中。也许是在searchText您未与我们共享的更新代码中(这会通过触发查询didSet)。很难说。但这在您提供的代码片段中似乎不是问题。
但是,在进行调试时,请确保不要在第一次调用表视图委托方法时和第二次调用时(由responseJSON块触发)合并它们。通过消除中的硬编码“ 6” numberOfRowsInSection,可以减少一些误报。
| 归档时间: | 
 | 
| 查看次数: | 2396 次 | 
| 最近记录: |