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
相关产品推荐
相关产品推荐

