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

SwiftUI列表无法显示API数据问题排查求助

问题根源分析

你代码的核心问题出在API服务的异步处理逻辑错误:

  • getNearestThreads是异步网络请求,但你用了同步返回值的写法。网络请求还没开始执行(task.resume()是异步启动),函数就直接返回了初始的空messageThreads数组。后续网络请求完成后修改messageThreads的操作,根本不会影响已经返回给ViewModel的那个空数组。
  • ViewModel里try? api.getNearestThreads(...)拿到的永远是空数组,所以messages被设为空,列表自然不显示内容。
修复方案

推荐用Swift 5.5+的async/await来处理异步请求,逻辑更清晰,也避免闭包嵌套的问题。

1. 修改API服务代码

把同步返回改成异步函数:

func getNearestThreads(query: String) async throws -> [MessageThread] {
    guard var urlComponents = URLComponents(string: API_URL) else {
        throw ApiServiceError.invalidURL
    }
    urlComponents.queryItems = [URLQueryItem(name: "uid", value: query)]
    
    guard let url = urlComponents.url else {
        throw ApiServiceError.invalidURL
    }
    
    let (data, response) = try await URLSession.shared.data(from: url)
    guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
        throw ApiServiceError.invalidResponse
    }
    
    guard let threads = parse(json: data) else {
        throw ApiServiceError.unableToParse(data: data)
    }
    return threads
}

// 补充对应的错误枚举(如果没有的话)
enum ApiServiceError: Error {
    case invalidURL
    case invalidResponse
    case unableToParse(data: Data)
}

2. 修改ViewModel代码

适配异步函数调用,确保错误和数据更新逻辑正确:

final class ChatListViewModel: ObservableObject {
    @Published var messages: [MessageThread] = []
    @Published var hasError = false

    func getNearbyThreads(identifier: String) {
        Task {
            do {
                let api = ApiService()
                let data = try await api.getNearestThreads(query: identifier)
                // Task在View环境中启动时,默认会回到主线程更新@Published属性
                self.messages = data
                self.hasError = false
            } catch {
                print(error)
                self.messages = []
                self.hasError = true
            }
        }
    }
}

3. 视图代码无需修改

你的ChatListView代码保持原样即可,ViewModel的messages是@Published属性,更新后会自动触发视图刷新。

额外说明
  • 你之前怀疑的两次DispatchQueue.main.async不是问题核心,真正的问题是网络请求的异步逻辑和同步返回值不匹配。
  • 用async/await替代传统的dataTask闭包,代码更简洁易维护,也符合当前Swift的最佳实践。

内容的提问来源于stack exchange,提问作者HarryMoy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 03:40:22