如何在用户无网络连接时禁用所有UIViewController的用户交互?
嘿,这个需求挺实用的,我来给你一步步捋清楚怎么实现👇
无网络时全局禁用UIViewController用户交互的方案
1. 先搞定网络状态的全局通知
既然你已经有了检测网络的方法,那第一步就是把网络状态的变化广播给所有页面。我们可以用NotificationCenter来做这件事:
// 先定义一个专属的通知名称,避免和其他通知冲突 extension Notification.Name { static let networkStatusUpdated = Notification.Name("NetworkStatusUpdated") } // 当你检测到网络状态变化时,发送这个通知 func broadcastNetworkStatus() { let isConnected = isConnectedToNetwork() // 这里用你已有的网络检测方法 NotificationCenter.default.post( name: .networkStatusUpdated, object: nil, userInfo: ["isConnected": isConnected] ) }
如果你的网络检测是实时的(比如用监听回调),那就在状态变化时调用broadcastNetworkStatus();如果是定时检测,就在每次检测后调用就行。
2. 给所有UIViewController加个扩展
为了不用每个VC都写重复代码,我们给UIViewController写个扩展,让所有页面自动拥有处理网络状态的能力:
extension UIViewController { // 注册网络状态监听的方法 func setupNetworkInteractionHandler() { // 监听网络状态变化通知 NotificationCenter.default.addObserver( self, selector: #selector(handleNetworkChange(_:)), name: .networkStatusUpdated, object: nil ) // 页面加载时先检查一次当前网络状态 checkInitialNetworkStatus() } // 初始化时检查网络状态并更新UI交互 private func checkInitialNetworkStatus() { let isConnected = isConnectedToNetwork() updateUserInteraction(enabled: isConnected) } // 处理网络状态变化的回调 @objc private func handleNetworkChange(_ notification: Notification) { guard let isConnected = notification.userInfo?["isConnected"] as? Bool else { return } updateUserInteraction(enabled: isConnected) } // 更新用户交互状态,同时添加/移除无网络提示遮罩 private func updateUserInteraction(enabled: Bool) { view.isUserInteractionEnabled = enabled // 给用户加个无网络提示的遮罩,体验更好 let maskTag = 999 // 用tag标记遮罩,方便后续移除 if !enabled { let noNetworkMask = UIView(frame: view.bounds) noNetworkMask.backgroundColor = UIColor.black.withAlphaComponent(0.6) noNetworkMask.tag = maskTag let tipLabel = UILabel() tipLabel.text = "当前无网络连接,请检查网络后重试" tipLabel.textColor = .white tipLabel.textAlignment = .center tipLabel.numberOfLines = 0 tipLabel.frame = CGRect(x: 40, y: view.center.y - 60, width: view.bounds.width - 80, height: 120) noNetworkMask.addSubview(tipLabel) view.addSubview(noNetworkMask) } else { // 网络恢复后移除遮罩 view.viewWithTag(maskTag)?.removeFromSuperview() } } // 页面销毁时移除监听,避免内存泄漏 deinit { NotificationCenter.default.removeObserver(self, name: .networkStatusUpdated, object: nil) } }
3. 让所有VC用上这个功能
有两种省心的方式:
- 方式一:手动调用:在每个VC的
viewDidLoad里加一行代码:
override func viewDidLoad() { super.viewDidLoad() setupNetworkInteractionHandler() }
- 方式二:自定义基类:创建一个
BaseViewController,让所有VC都继承它,在基类的viewDidLoad里自动调用方法,彻底解放双手:
class BaseViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() setupNetworkInteractionHandler() } } // 其他VC直接继承BaseViewController就行 class HomeViewController: BaseViewController { // ... 你的业务代码 }
额外小优化(iOS 12+)
如果你的APP支持iOS12及以上,推荐用苹果原生的NWPathMonitor实时监听网络变化,比定时检测更高效:
import Network class NetworkMonitor { static let shared = NetworkMonitor() private let monitor = NWPathMonitor() private(set) var isConnected = false private init() { monitor.pathUpdateHandler = { [weak self] path in self?.isConnected = path.status == .satisfied // 状态变化时自动发送通知 NotificationCenter.default.post( name: .networkStatusUpdated, object: nil, userInfo: ["isConnected": self?.isConnected ?? false] ) } let queue = DispatchQueue(label: "NetworkMonitorQueue") monitor.start(queue: queue) } }
这样就能实时感知网络状态变化,用户体验会更流畅~
内容的提问来源于stack exchange,提问作者Karliene
相关产品推荐
相关产品推荐

