Swift4中如何实现同步网络请求?
解决iOS中同步执行网络请求的问题
嘿,看你在viewDidLoad里尝试用DispatchGroup来让登录这类网络请求同步执行,确保后续代码等请求完成再继续对吧?这个思路没问题,但有几个关键细节得注意,不然容易踩坑。我给你梳理下正确的实现方式和避坑点:
核心实现思路
网络请求本身是异步的,我们用DispatchGroup来标记任务的开始和结束,然后在后台队列等待任务完成,避免阻塞主队列(主队列阻塞会导致UI卡顿甚至APP被系统终止)。
完整代码示例
override func viewDidLoad() { super.viewDidLoad() // 打印应用支持目录路径 let appSupportPath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last! print(appSupportPath) // 启动加载动画 waitView.startAnimating() waitView.hidesWhenStopped = true let group = DispatchGroup() print("准备发起登录请求") // 标记任务开始 group.enter() OdooAuth.init( successBlock: { [weak self] authResult in // 处理登录成功逻辑,比如保存认证信息 print("登录成功:\(authResult)") // 标记任务结束,必须调用! group.leave() }, failureBlock: { [weak self] error in // 处理登录失败逻辑,比如提示用户 print("登录失败:\(error.localizedDescription)") // 失败分支也要标记任务结束,否则group会无限等待 group.leave() } ) // 转到后台队列等待任务完成,绝对不能在主队列调用wait! DispatchQueue.global(qos: .userInitiated).async { // 等待登录请求完成(可设置超时) let waitResult = group.wait(timeout: .now() + 15) DispatchQueue.main.async { [weak self] in self?.waitView.stopAnimating() switch waitResult { case .success: // 登录完成后执行的逻辑,比如跳转到首页、加载业务数据 print("登录流程完成,继续执行后续操作") case .timedOut: // 处理超时逻辑,比如提示用户网络不佳 print("登录请求超时,请检查网络后重试") } } } }
关键注意事项
- 必须在所有分支调用
group.leave():不管请求成功、失败还是超时,只要调用了group.enter(),就一定要对应调用group.leave(),否则group.wait()会无限等待,导致线程挂起。 - 绝对不在主队列调用
group.wait():主队列负责UI渲染,阻塞主队列会让APP失去响应,严重时会被系统判定为无响应而杀掉。一定要放到后台队列执行等待操作。 - 用
[weak self]避免循环引用:闭包里引用self时记得用弱引用,防止内存泄漏。 - 设置超时时间更稳妥:给
group.wait()加上超时参数,避免因为网络异常导致无限等待,提升用户体验。
内容的提问来源于stack exchange,提问作者Augusto
相关产品推荐
相关产品推荐

