iOS开发:UISearchController+TableView无法展示API搜索城市数据排查
搞定你的TableView不显示搜索结果问题!
嘿,看了你的代码和日志,API请求确实跑通了,但TableView没数据,核心问题是异步请求的结果没正确更新到数据源,还有几个逻辑小bug。下面一步步给你修复:
1. 最关键的问题:异步请求结果没存到数据源
你调用fetchCurrentWeather的时候,completionHandler是空的!网络请求是后台异步跑的,当API返回天气数据时,你根本没把它加到weatherArray里,那TableView当然没东西可显示啊!
改法:
把completionHandler填上,而且要回到主线程更新UI(后台线程不能碰UI):
func updateSearchResults(for searchController: UISearchController) { guard let searchText = searchController.searchBar.text, !searchText.isEmpty else { // 搜索文本为空时清空结果 weatherArray.removeAll() tblView.reloadData() return } print("Search text: \(searchText)") mWeather.fetchCurrentWeather(city: searchText) { [weak self] weather in // 必须切回主线程更新UI和数据源 DispatchQueue.main.async { // 这里假设每次搜索返回一个城市,直接替换数组;如果要支持多结果就用append self?.weatherArray = [weather] self?.tblView.reloadData() } } }
2. searching变量的逻辑完全错了
你现在判断weatherArray.count >0就认为是搜索状态,这完全不对!正确的应该是看搜索控制器是不是正在活跃,而且搜索框有内容。
改法:
var searching: Bool { return searchController.isActive && !searchController.searchBar.text!.isEmpty }
3. cellForRowAt里别瞎调用reloadData()
你在cell创建的时候还调用tblView.reloadData(),这会无限循环的!reloadData会触发cellForRowAt,cellForRowAt又调用reloadData,直接卡爆或者崩溃,赶紧删掉这两行!
改完的cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "searchCell", for: indexPath) if searching { cell.textLabel?.text = weatherArray[indexPath.row].name } else { cell.textLabel?.text = filteredWeatherArray[indexPath.row] } return cell }
4. 默认状态下没数据?因为filteredWeatherArray是空的
你有个originalArray模拟数据,但从来没赋值给filteredWeatherArray,所以默认打开APP的时候TableView也是空的。在viewDidLoad里初始化一下:
改法:
override func viewDidLoad() { super.viewDidLoad() searchController.searchResultsUpdater = self searchController.obscuresBackgroundDuringPresentation = false searchController.searchBar.placeholder = "type in your city here" navigationItem.searchController = searchController // 把模拟数据赋值给默认数据源 filteredWeatherArray = originalArray tblView.delegate = self tblView.dataSource = self }
最后再检查几个小细节
- 如果你的API支持一次搜索返回多个城市,把
self?.weatherArray = [weather]改成self?.weatherArray.append(weather),但记得每次搜索前先清空数组,避免重复数据。 - 确保你的
WeatherStruct里的name属性是正确解析的,日志里已经打印了wdata.name,应该没问题。
这样改完之后,搜索城市就能在TableView里显示结果,默认状态也能看到你那堆模拟城市啦!
内容的提问来源于stack exchange,提问作者Johannes
相关产品推荐
相关产品推荐

