You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 17:12:53