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

如何监听自定义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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 21:42:41