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

如何在macOS Cocoa中监听自定义NSWindow的isVisible属性变化?

监听NSWindow子类isVisible属性变化(非Combine方案)

方案一:重写窗口生命周期方法

isVisible是计算属性,它的变化对应窗口显示/隐藏、最小化/恢复、关闭等操作,直接重写这些触发状态变更的方法,就能精准捕获状态变化:

import Cocoa

class MyNSWindow: NSWindow {
    // 记录上一次状态,避免重复触发逻辑
    private var lastVisibleState = false
    
    override func orderFront(_ sender: Any?) {
        super.orderFront(sender)
        checkVisibilityChange()
    }
    
    override func orderBack(_ sender: Any?) {
        super.orderBack(sender)
        checkVisibilityChange()
    }
    
    override func miniaturize(_ sender: Any?) {
        super.miniaturize(sender)
        checkVisibilityChange()
    }
    
    override func deminiaturize(_ sender: Any?) {
        super.deminiaturize(sender)
        checkVisibilityChange()
    }
    
    override func close() {
        super.close()
        checkVisibilityChange()
    }
    
    // 统一处理状态变化逻辑
    private func checkVisibilityChange() {
        let currentVisible = isVisible
        guard currentVisible != lastVisibleState else { return }
        lastVisibleState = currentVisible
        
        if currentVisible {
            print("窗口已显示")
            // 这里添加窗口显示后的自定义逻辑
        } else {
            print("窗口已隐藏/关闭/最小化")
            // 这里添加窗口隐藏后的自定义逻辑
        }
    }
}

这种方式直接绑定窗口操作行为,逻辑清晰,不需要额外依赖KVO机制。

方案二:使用KVO监听isVisible属性

NSWindow的isVisible属性支持KVO,我们可以通过原生KVO API监听变化:

import Cocoa

class MyNSWindow: NSWindow {
    private var visibilityObservation: NSKeyValueObservation?
    
    override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing backingStoreType: NSWindow.BackingStoreType, defer flag: Bool) {
        super.init(contentRect: contentRect, styleMask: style, backing: backingStoreType, defer: flag)
        setupVisibilityObserver()
    }
    
    private func setupVisibilityObserver() {
        visibilityObservation = observe(\.isVisible, options: [.old, .new]) { window, change in
            let oldState = change.oldValue ?? false
            let newState = change.newValue ?? false
            
            if oldState != newState {
                if newState {
                    print("窗口变为可见")
                    // 处理显示逻辑
                } else {
                    print("窗口变为不可见")
                    // 处理隐藏逻辑
                }
            }
        }
    }
}

这里的NSKeyValueObservation会和窗口实例弱绑定,窗口释放时会自动清理监听,无需手动移除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:00:49