如何正确处理并完成接收@escaping函数的API函数调用?
问题解析与解决方案
一、API函数声明拆解
先看specialStruct里的context函数:
public func context(completion: @escaping ((Result<String, SpecialClassError>) -> Void)) { class.something() { result in switch result { case .success(let response): completion(.success(response.cid)) case.failure(let error): completion(.failure(.network(error: error), data: nil))) } } }
逐个点解释:
@escaping:这个标记说明传入的闭包不会跟着context函数一起结束。因为class.something()是异步操作(比如网络请求),得等它做完才会触发这个闭包,所以必须用@escaping告诉编译器:这个闭包要“逃”出去,稍后再执行。Result<String, SpecialClassError>:这是Swift专门用来处理异步结果的类型,二选一:- 成功时返回
String类型的cid; - 失败时返回自定义的
SpecialClassError错误,这里是.network类型的错误,还带了原始错误信息。
- 成功时返回
- 函数逻辑:内部调用了一个异步的
class.something(),等它拿到结果后,转成Result格式,再通过你传入的completion闭包把结果回调给调用者。
二、调用卡住的问题修复
你把调用放在SwiftUI View的init()里,出现回调执行完但卡在系统代码的情况,主要是这几个原因:
1. 别在View的init()里跑异步操作
SwiftUI的init()是主线程同步执行的,View还没初始化完成就发起异步请求,很容易导致线程调度或者资源释放出问题。
改法:
把调用移到onAppear修饰符里,这是SwiftUI官方推荐的初始化异步操作的时机:
struct YourView: View { var body: some View { Text("你的页面内容") .onAppear { specialStruct.context { result in switch result { case .success(let str): print(str) case .failure(let error): print(error.localizedDescription) } } } } }
2. 提前防范循环引用(后续扩展必加)
现在你回调里没用到self,暂时没问题,但如果之后要修改View的状态(比如@State变量),必须加[weak self]防止循环引用:
.onAppear { specialStruct.context { [weak self] result in guard let self = self else { return } switch result { case .success(let str): print(str) // 比如修改View的状态 // self.cid = str case .failure(let error): print(error.localizedDescription) } } }
3. 调试工具的干扰(大概率原因)
你提到卡在FPRNSURL...nInstrument那行,这基本是Xcode的调试插件(比如Firebase性能监控、其他埋点工具)注入的代码,不是你的业务代码问题。可以试试:
- 去Scheme设置里禁用这类性能监控工具;
- 切换到Release模式运行,验证是否还会卡住;
- 重启Xcode和设备,清除缓存。
4. 回调切回主线程(更新UI必备)
网络请求的回调一般在后台线程,如果之后要更新UI,必须切回主线程:
specialStruct.context { result in DispatchQueue.main.async { switch result { case .success(let str): print(str) // 这里可以安全更新UI case .failure(let error): print(error.localizedDescription) } } }
总结
@escaping就是给异步闭包用的,告诉编译器这个闭包要等异步操作完成后再执行;- SwiftUI里别在
init()里跑异步操作,改用onAppear; - 卡在系统代码先排查调试工具的干扰;
- 更新UI一定要切回主线程执行。
内容的提问来源于stack exchange,提问作者J Smooth
相关产品推荐
相关产品推荐

