Swift中使用Future和DispatchQueue编译报错问题求助
问题描述
开发Swift应用时,为避免读取JSON文件阻塞主线程,尝试用Future和DispatchQueue在后台执行操作,代码如下:
func getFeed() -> Future<[ios_foodloose_app.FeedItemEntity], Error> { return Future<[FeedItemEntity], Error> { promise in guard let url = Bundle(for: MockedFeedService.self).url(forResource: "basic-test-feed-response",withExtension: "json"), let data = try? Data(contentsOf: url) else { return promise(.failure(NSError(domain: "", code: 401, userInfo: [ NSLocalizedDescriptionKey: "Error"]))) } do { DispatchQueue.global(qos: .background).async { let response = try JSONDecoder().decode( [FeedItemEntity].self, from: data) DispatchQueue.main.async { promise(.success(response)) } } } catch { print("JSON Decode error: \(error)") promise(.failure(error)) } } }
Xcode在DispatchQueue.global(qos: .background).async {行报错,错误信息:
Invalid conversion from throwing function of type '@Sendable () throws -> Void' to non-throwing function type '@Sendable @convention(block) () -> Void'
修复方案
错误原因
DispatchQueue.async接受的闭包是非抛出类型,但你在闭包内直接使用了try JSONDecoder().decode(会抛出错误),导致类型不匹配。另外原代码中Data(contentsOf:)是同步操作,当前在主线程执行,依然可能阻塞主线程,需要一并移到后台处理。
修正步骤
- 将文件读取、JSON解码的全部操作移到后台线程,避免主线程阻塞
- 在后台闭包内部用
do-catch处理解码错误,捕获后通过promise传递失败结果 - 最终调用
promise时切换回主线程(适配UI更新场景,若后续无UI操作可省略)
修正后的代码
func getFeed() -> Future<[ios_foodloose_app.FeedItemEntity], Error> { return Future<[FeedItemEntity], Error> { promise in DispatchQueue.global(qos: .background).async { do { guard let url = Bundle(for: MockedFeedService.self).url(forResource: "basic-test-feed-response", withExtension: "json") else { throw NSError(domain: "", code: 401, userInfo: [NSLocalizedDescriptionKey: "JSON文件未找到"]) } let data = try Data(contentsOf: url) let response = try JSONDecoder().decode([FeedItemEntity].self, from: data) DispatchQueue.main.async { promise(.success(response)) } } catch { print("处理JSON出错: \(error)") DispatchQueue.main.async { promise(.failure(error)) } } } } }
额外说明
- 把
Data(contentsOf:)移到后台后,主线程不会被文件读取操作阻塞 - 所有可能抛出错误的操作都放在后台闭包的
do块内,统一用catch捕获后传递结果 - 切换回主线程调用
promise,是因为多数场景下Future的回调会涉及UI更新,而UI操作必须在主线程执行
内容的提问来源于stack exchange,提问作者Seb
相关产品推荐
相关产品推荐

