如何等待已启动的NetworkHandler初始化异步加载函数完成?
解决NetworkHandler初始化加载完成的监听问题
这是个很常见的异步状态同步场景,我给你几个从简单到优雅的解决方案,你可以根据项目的iOS版本复杂度来选择:
方案1:闭包回调(轻量直接)
直接在NetworkHandler的初始化方法里传入加载完成的回调,这样创建实例时就能绑定后续逻辑,不需要依赖本地变量判断:
class NetworkHandler { private(set) var initialLoadIsDone = false // 初始化时传入加载完成回调 init(onInitialLoadComplete: (() -> Void)?) { loadData(completion: onInitialLoadComplete) } private func loadData(completion: (() -> Void)?) { // 模拟异步加载逻辑 DispatchQueue.global().asyncAfter(deadline: .now() + 2) { [weak self] in self?.initialLoadIsDone = true // 回到主线程执行UI操作 DispatchQueue.main.async { completion?() } } } }
ViewController中的用法:
class ViewController: UIViewController { var networkHandler: NetworkHandler? override func viewDidLoad() { super.viewDidLoad() showLoadingIndicator() // 创建实例时绑定完成回调 networkHandler = NetworkHandler { [weak self] in self?.hideLoadingIndicator() self?.showContent() } } private func showLoadingIndicator() { // 展示加载指示器的逻辑 } private func hideLoadingIndicator() { // 隐藏加载指示器的逻辑 } private func showContent() { // 展示正常界面的逻辑 } }
方案2:Combine响应式(iOS 13+ 推荐)
如果你的项目支持iOS 13及以上,用Combine框架来发布状态变化会更优雅,适合复杂的状态监听场景:
import Combine class NetworkHandler { private(set) var initialLoadIsDone = false // 定义一个发布者,用于发送加载完成事件 let initialLoadComplete = PassthroughSubject<Void, Never>() init() { loadData() } private func loadData() { DispatchQueue.global().asyncAfter(deadline: .now() + 2) { [weak self] in guard let self = self else { return } self.initialLoadIsDone = true // 发送完成事件 self.initialLoadComplete.send() self.initialLoadComplete.send(completion: .finished) } } }
ViewController中的订阅逻辑:
class ViewController: UIViewController { var networkHandler: NetworkHandler? private var cancellables = Set<AnyCancellable>() override func viewDidLoad() { super.viewDidLoad() guard let handler = networkHandler else { return } if handler.initialLoadIsDone { showContent() } else { showLoadingIndicator() // 订阅加载完成事件,自动切换到主线程 handler.initialLoadComplete .receive(on: DispatchQueue.main) .sink { [weak self] in self?.hideLoadingIndicator() self?.showContent() } .store(in: &cancellables) } } // 省略showLoadingIndicator等方法 }
方案3:Delegate模式(传统可靠)
如果需要兼容更低版本iOS,或者习惯用Delegate解耦逻辑,可以定义一个协议来传递加载完成事件:
// 定义代理协议 protocol NetworkHandlerDelegate: AnyObject { func networkHandlerDidFinishInitialLoad(_ handler: NetworkHandler) } class NetworkHandler { private(set) var initialLoadIsDone = false weak var delegate: NetworkHandlerDelegate? init() { loadData() } private func loadData() { DispatchQueue.global().asyncAfter(deadline: .now() + 2) { [weak self] in guard let self = self else { return } self.initialLoadIsDone = true // 回到主线程通知代理 DispatchQueue.main.async { self.delegate?.networkHandlerDidFinishInitialLoad(self) } } } }
ViewController实现代理:
class ViewController: UIViewController, NetworkHandlerDelegate { var networkHandler: NetworkHandler? override func viewDidLoad() { super.viewDidLoad() networkHandler?.delegate = self if networkHandler?.initialLoadIsDone == true { showContent() } else { showLoadingIndicator() } } // 实现代理方法 func networkHandlerDidFinishInitialLoad(_ handler: NetworkHandler) { hideLoadingIndicator() showContent() } // 省略其他方法 }
方案选择建议
- 如果是小型项目或快速迭代,闭包回调最直接轻量;
- 如果项目已经使用Combine或需要处理复杂状态流,Combine方案是最优雅的选择;
- 如果需要兼容iOS 12及以下,或者团队习惯用Delegate模式,Delegate方案更可靠。
内容的提问来源于stack exchange,提问作者Sonius
相关产品推荐
相关产品推荐

