如何监听自定义UIView的添加与移除?能否通过NotificationCenter实现?
解答:通过NotificationCenter监听UIView的添加与移除时机
当然可以实现这两个需求!我们可以借助UIView的生命周期方法,配合NotificationCenter来在视图即将被展示或移除时发送通知。下面分步骤给你详细说明:
一、核心思路:利用UIView的生命周期方法
UIView提供了willMove(toSuperview:)方法,它会在视图的父视图即将发生变化时被调用——不管是即将添加到父视图(此时newSuperview不为nil),还是即将从父视图移除(此时newSuperview为nil),都能精准捕捉到这个时机,完美匹配你的需求。
二、具体实现步骤
1. 创建自定义UIView子类
首先,我们需要把你原来的UIView替换成自定义子类,把通知发送的逻辑封装在视图内部:
import UIKit class TemporaryView: UIView { // 定义专属的通知名称,方便外部统一监听 static let willBeAddedNotification = Notification.Name("TemporaryViewWillBeAdded") static let willBeRemovedNotification = Notification.Name("TemporaryViewWillBeRemoved") override func willMove(toSuperview newSuperview: UIView?) { super.willMove(toSuperview: newSuperview) // 根据newSuperview的状态判断是添加还是移除操作 if newSuperview != nil { // 即将被添加到父视图,发送通知 NotificationCenter.default.post( name: Self.willBeAddedNotification, object: self // 可以把当前视图作为object传递,方便监听者识别 ) } else { // 即将被从父视图移除,发送通知 NotificationCenter.default.post( name: Self.willBeRemovedNotification, object: self ) } } }
2. 修改你的视图初始化代码
把原来的UIView替换成我们的自定义子类:
lazy var temporary: TemporaryView = { let view = TemporaryView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) view.backgroundColor = .white return view }()
3. 在需要监听的地方添加通知观察者
比如在你的视图控制器中,监听这两个通知并处理逻辑:
class YourViewController: UIViewController { lazy var temporary: TemporaryView = { let view = TemporaryView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) view.backgroundColor = .white return view }() override func viewDidLoad() { super.viewDidLoad() // 添加通知观察者 NotificationCenter.default.addObserver( self, selector: #selector(handleViewWillBeAdded(_:)), name: TemporaryView.willBeAddedNotification, object: nil ) NotificationCenter.default.addObserver( self, selector: #selector(handleViewWillBeRemoved(_:)), name: TemporaryView.willBeRemovedNotification, object: nil ) } // 处理视图即将被添加的逻辑 @objc private func handleViewWillBeAdded(_ notification: Notification) { if let tempView = notification.object as? TemporaryView { print("临时视图即将被展示:\(tempView)") // 这里可以添加你需要的业务逻辑,比如更新状态、加载数据等 } } // 处理视图即将被移除的逻辑 @objc private func handleViewWillBeRemoved(_ notification: Notification) { if let tempView = notification.object as? TemporaryView { print("临时视图即将被移除:\(tempView)") // 这里可以添加清理资源、保存状态等逻辑 } } // 记得在控制器销毁时移除观察者,避免内存泄漏 deinit { NotificationCenter.default.removeObserver(self) } }
三、补充说明
- 为什么用
willMove(toSuperview:)而不是didMoveToSuperview()?
因为willMove(toSuperview:)是即将发生变化时调用,刚好符合你“即将被展示/移除”的需求;而didMoveToSuperview()是变化完成后才调用,时机稍晚。 - 如果不想自定义子类?
也可以用KVO监听superview属性,但这种方式需要手动管理观察者的添加和移除,容易出现内存泄漏或崩溃问题,不如自定义子类优雅,所以更推荐前者。
内容的提问来源于stack exchange,提问作者Ice
相关产品推荐
相关产品推荐

