arrays - 如何修复 JSON 解析应用程序中的 'Index Out Of Range' 错误

标签 arrays swift

我发现我的 code 有一个小问题。我遇到的问题是我的限制调用工作正常,但是如果您运行它并多次切换显示的金额选项,则会出现索引超出范围错误。

似乎只有当您快速运行它或不更改搜索时才会发生这种情况。我花了 4 个小时在这上面,感觉我没有看到一些真正简单的东西!谢谢!

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath)

        let searchResult = searchResultsController.searchResults[indexPath.row]
        cell.textLabel?.text = searchResult.title
        cell.detailTextLabel?.text = searchResult.creator
        return cell
    }

    //MARK: Actions

    @IBAction func filterButtonPressed(_ sender: UIBarButtonItem) {
        if limitSearchButton.title == "show 10" {
            limit.limit = "10"
            limitSearchButton.title = "show 5"
            print("limit is \(String(describing: limit.limit))")
            searchBarSearchButtonClicked(searchBar)
            tableView.reloadData()
        } else if limitSearchButton.title == "show 5"{
            limit.limit = "5"
            limitSearchButton.title = "show 10"
            print("limit is \(String(describing: limit.limit))")
            searchBarSearchButtonClicked(searchBar)
            tableView.reloadData()
        }

    }

    @IBAction func segmentedControlChanged(_ sender: UISegmentedControl) {
        if sender.selectedSegmentIndex == 0 {
            searchBarSearchButtonClicked(searchBar)
            self.tableView.reloadData()
        }else if sender.selectedSegmentIndex == 1 {
            searchBarSearchButtonClicked(searchBar)
            self.tableView.reloadData()
        }else {
            searchBarSearchButtonClicked(searchBar)
            self.tableView.reloadData()
        }
    }


}

extension SearchResultsTableViewController: UISearchBarDelegate {
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        guard let searchTerm = searchBar.text else { return }

        switch segmentedControl.selectedSegmentIndex {
        case 0:
            resultType = .software
        case 1:
            resultType = .musicTrack
        case 2:
            resultType = .movie
        default:
            break
        }
        searchResultsController.performSearch(searchTerm: searchTerm, resultType: resultType, limit: limit) {
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }
    }
}

我希望通过我的打印语句和过滤功能,获得限制金额并将其与更新我的按钮一起返回。但在使用了几次 UIBarButton 函数后我什么也没得到。

最佳答案

为什么崩溃?

这是线程之间的竞争条件(当您异步获取新结果时)。

有时您尝试显示 4 个元素,但您的数据源刚刚更新,现在有 3 个元素。您在模型更改方面缺乏同步。

通过对 reloadData 的所有调用,很有可能与网络请求返回的时间相同,我怀疑这会导致崩溃。

API 修复

强制并发的一种方法是将所有并发同步工作移至 API,这样 API 的使用者就不必考虑它是如何工作的。 (不再有客户端调度异步调用)

在 API 逻辑中,使用 DispatchQueue.main.async { } block 包装每个 completion() 处理程序调用,以及对 ViewController 中访问的公共(public)属性的更改。该调度队列将强制确保不同线程上不会发生 UI 更新。

您在 ViewController 中调用的任何 API 都将位于同一主线程上,因此只要将这些 block 放在每个适当的位置,您就可以获得线程安全。

由于您没有提供该代码,我将提供另一个 iOS 项目的代码示例,地址为 Lambda School .

您的 URLSession/网络代码中的逻辑将如下所示:

URLSession.shared.dataTask(with: url) { (data, _, error) in
    if let error = error {
        print("Error fetching quakes: \(error)")
        DispatchQueue.main.async { // Wrap every call to completion()
            completion(nil, error)
        }
        return
    }

    guard let data = data else {
        DispatchQueue.main.async {
            completion(nil, QuakeError.noDataReturned)
        }
        return
    }

    do {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .millisecondsSince1970

        let quakeResults = try decoder.decode(QuakeResults.self, from: data)

        DispatchQueue.main.async {
            // Setting a public property needs to be also protected
            // inside your main.async blocks, in addition to your 
            // completion() handler calls

            self.quakes = quakeResults.features  // protect public properties
            completion(quakes, nil)
        }
    } catch {
        DispatchQueue.main.async {
            completion(nil, error)
        }
    }

}.resume()

关于arrays - 如何修复 JSON 解析应用程序中的 'Index Out Of Range' 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58679040/

相关文章:

java - 如何分组到数组映射中?

javascript - JS中字符串的格式化输出

ios - 如何处理 NSExtensionActivationRule is truepredicate?

swift - 在 Swift 中将 NSData 添加到 UIActivityViewController 电子邮件

ios - EXC_BAD_ACCESS 当访问从另一个方法返回的 fetchrequest 的结果时

php - 在 foreach 的每次迭代中创建新数组

c++ - 二维 vector 数组的优点

进行公差分析的代码

ios - 自定义 UIButton Swift 2.0

ios - 子类化 Material View 不显示 Material 深度