Replace per-VC activity indicators with a ref-counted GlobalLoadingManager, and resolve duplicate show/hide calls on Profile, Statistics, and Home tabs. Co-authored-by: Cursor <cursoragent@cursor.com>
75 lines
2.0 KiB
Swift
75 lines
2.0 KiB
Swift
//
|
||
// GlobalLoadingManager.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import UIKit
|
||
|
||
/// 全局 Loading 管理器,对齐 Android `GlobalLoadingManager`。
|
||
@MainActor
|
||
final class GlobalLoadingManager {
|
||
|
||
static let shared = GlobalLoadingManager()
|
||
|
||
private var loadingCount = 0
|
||
private weak var hostWindow: UIWindow?
|
||
private var overlayView: GlobalLoadingOverlayView?
|
||
|
||
private init() {}
|
||
|
||
/// 当前是否正在展示 Loading。
|
||
var isShowing: Bool {
|
||
loadingCount > 0
|
||
}
|
||
|
||
/// 增加 Loading 引用计数并展示遮罩。
|
||
func show() {
|
||
loadingCount += 1
|
||
guard loadingCount == 1 else { return }
|
||
attachOverlayIfNeeded()
|
||
overlayView?.present()
|
||
}
|
||
|
||
/// 减少 Loading 引用计数,归零后立即隐藏遮罩。
|
||
func hide() {
|
||
guard loadingCount > 0 else { return }
|
||
loadingCount -= 1
|
||
guard loadingCount == 0 else { return }
|
||
overlayView?.dismiss()
|
||
overlayView?.removeFromSuperview()
|
||
}
|
||
|
||
/// 强制关闭所有 Loading。
|
||
func hideAll() {
|
||
loadingCount = 0
|
||
overlayView?.dismiss()
|
||
overlayView?.removeFromSuperview()
|
||
}
|
||
|
||
private func attachOverlayIfNeeded() {
|
||
guard let window = keyWindow else { return }
|
||
hostWindow = window
|
||
|
||
if overlayView == nil {
|
||
let overlay = GlobalLoadingOverlayView(frame: window.bounds)
|
||
overlay.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||
overlay.isHidden = true
|
||
overlayView = overlay
|
||
}
|
||
|
||
guard let overlayView else { return }
|
||
if overlayView.superview !== window {
|
||
overlayView.removeFromSuperview()
|
||
window.addSubview(overlayView)
|
||
}
|
||
window.bringSubviewToFront(overlayView)
|
||
}
|
||
|
||
private var keyWindow: UIWindow? {
|
||
UIApplication.shared.connectedScenes
|
||
.compactMap { $0 as? UIWindowScene }
|
||
.flatMap(\.windows)
|
||
.first { $0.isKeyWindow }
|
||
}
|
||
}
|