Swift中如何监听macOS外接显示器连接与断开状态变化
macOS监听外接显示器插拔事件的实现方案
监听外接显示器连接/断开的核心方案是使用系统原生的NSApplication.didChangeScreenParametersNotification通知,该通知会在所有屏幕参数发生变更时触发,包含外接显示器的插拔、分辨率调整、屏幕排列修改等场景。
完整实现代码
import AppKit class DisplayConnectionMonitor { // 存储上一次统计的屏幕数量,用于对比判断是否发生插拔 private var previousScreenCount = NSScreen.screens.count private var notificationObserver: NSObjectProtocol? /// 启动显示器插拔监听 func startMonitor() { notificationObserver = NotificationCenter.default.addObserver( forName: NSApplication.didChangeScreenParametersNotification, object: nil, queue: .main ) { [weak self] _ in guard let self = self else { return } let currentScreenCount = NSScreen.screens.count // 仅当屏幕数量发生变化时执行对应逻辑,过滤分辨率调整等其他触发场景 guard currentScreenCount != previousScreenCount else { return } if currentScreenCount > previousScreenCount { print("外接显示器已连接,当前屏幕总数:\(currentScreenCount)") // 此处填写显示器连接后需要执行的逻辑 } else { print("外接显示器已断开,当前屏幕总数:\(currentScreenCount)") // 此处填写显示器断开后需要执行的逻辑 } previousScreenCount = currentScreenCount } } /// 停止显示器插拔监听 func stopMonitor() { if let observer = notificationObserver { NotificationCenter.default.removeObserver(observer) notificationObserver = nil } } }
注意事项
- 若你开发的是命令行工具类项目,需要先初始化NSApplication实例才能正常接收该通知,普通GUI App无需额外配置。
- 单次显示器插拔可能触发多次通知,通过存储历史屏幕数量做对比可以避免重复执行逻辑。
原有方案失效原因说明
- KVO方案无法生效是因为
NSScreen.screens属性本身不支持KVO,且你之前的写法存在逻辑错误:KVO的监听对象必须是支持KVO的Objective-C类实例,而NSScreen.screens.count是普通Int值,无法作为被监听的KVO路径。 NSScreen.colorSpaceDidChangeNotification仅在单块屏幕的颜色空间参数变更时触发,和显示器插拔事件无关,因此无法收到对应通知。
内容的提问来源于stack exchange,提问作者SouthernYankee65
相关产品推荐
相关产品推荐

