You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中使用Protocol实现Loader如何避免重复显示且等全部请求结束再隐藏

现有方案可行性分析

你用计数控制Loader显隐的核心思路是完全可以满足需求的,但你当前的代码和「静态count」的选型存在明显问题:

  1. 首先你的代码无法直接编译:Swift 协议扩展不支持直接添加存储属性,你代码里用到的count没有定义,运行会报错。
  2. 如果使用静态count变量会出现跨实例干扰:静态变量属于类全局共享,如果你同时有多个UIViewController实例显示Loader,计数会全部算在一起,导致某个页面的Loader提前隐藏或者一直不消失。
  3. 存在线程安全隐患:如果showLoader/hideLoader在不同线程调用,count的加减操作不是原子性的,容易出现计数错误,最终导致Loader状态异常。

计数方案的正确实现

如果要保留计数逻辑,不要用静态变量,改用关联对象为每个UIViewController实例绑定独立的计数属性即可,参考实现代码:

import ObjectiveC.runtime

protocol Loader where Self: UIViewController {
    func showLoader()
    func hideLoader()
}

// 关联对象的key
private var loaderCountKey: UInt8 = 0
private let loaderQueue = DispatchQueue(label: "com.example.loader.queue") // 保证计数操作线程安全

extension Loader {
    private var count: Int {
        get {
            loaderQueue.sync {
                objc_getAssociatedObject(self, &loaderCountKey) as? Int ?? 0
            }
        }
        set {
            loaderQueue.async {
                objc_setAssociatedObject(self, &loaderCountKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }

    func showLoader() {
        let currentCount = count
        if currentCount == 0 {
            print("Show Loading")
            // 这里添加你的Loader视图到当前控制器的逻辑
        }
        count = currentCount + 1
    }

    func hideLoader() {
        let currentCount = count
        count = max(0, currentCount - 1)
        if count == 0 {
            print("Hide Loading")
            // 这里添加你的Loader移除逻辑
        }
    }
}

额外建议:可以在UIViewController的viewDidDisappear方法里加兜底逻辑,页面消失时直接把count置0并隐藏Loader,避免请求未返回页面销毁导致的Loader泄漏。


不用count的替代方案

如果不想自己维护计数,可以选以下更省心的实现:

  • Token引用计数方案:每次调用showLoader返回一个销毁令牌,当所有令牌都被释放(对应所有请求结束)时自动隐藏Loader。可以借助Combine的AnyCancellable实现,也可以自己封装简单的Token类,在deinit时自动执行隐藏逻辑。
  • 绑定请求管理器方案:如果你的项目有统一的API请求管理类,可以直接在管理器里维护当前页面的活跃请求数,请求发起时自动触发Loader显示,所有请求结束自动触发隐藏,不需要业务层手动调用show/hide方法。
  • 标识集合方案:用Set代替数字计数,每次发起请求生成唯一ID,show时把ID加入集合,hide时移除ID,集合为空时才隐藏Loader。这种方案可以避免同一个请求重复调用show导致的计数冗余,适合请求可能重试的场景。

内容的提问来源于stack exchange,提问作者Antony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:27:03