Mac锁屏/唤醒触发的事件是什么?为何监听NSNotification无响应?
解决Mac锁屏/唤醒的通知监听问题
嘿,我来帮你搞定这个困扰!先给你理清楚Mac锁屏/唤醒时的系统事件,再帮你排查为什么你的sleepListener没被调用。
一、Mac锁屏/唤醒会触发哪些系统事件?
系统会通过NSWorkspace的通知中心发送以下核心通知:
NSWorkspaceWillSleepNotification:系统即将进入睡眠(包括锁屏,因为手动或通过IORequestIdle触发的锁屏本质是触发系统空闲睡眠)NSWorkspaceDidWakeNotification:系统完成唤醒/解锁- 如果你需要区分屏幕休眠和系统整体睡眠,还有这两个:
NSWorkspaceScreensDidSleepNotification:屏幕进入休眠状态NSWorkspaceScreensDidWakeNotification:屏幕唤醒
二、你的sleepListener没被调用的常见原因
大概率是监听注册的方式不对,或者时机有问题,你可以逐一排查:
- 用错了通知中心:很多人会直接用
NotificationCenter.default注册,但系统睡眠/锁屏通知是通过NSWorkspace.shared.notificationCenter发送的,用默认通知中心肯定收不到! - 监听注册太晚:要确保在App启动完成时就注册监听,比如放在
applicationDidFinishLaunching方法里,别等到后面才注册。 - IORequestIdle没真正触发系统睡眠:可以先手动锁屏(比如按
Control+Shift+Power组合键)测试你的监听是否生效,如果手动锁屏能触发,那可能是IORequestIdle的调用参数或系统设置阻止了睡眠。
三、正确的监听实现代码
给你贴个Swift版本的AppDelegate示例,直接用就能生效:
import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { // 获取NSWorkspace的通知中心 let workspaceNotificationCenter = NSWorkspace.shared.notificationCenter // 注册锁屏/睡眠通知 workspaceNotificationCenter.addObserver( self, selector: #selector(sleepListener(_:)), name: NSWorkspaceWillSleepNotification, object: nil ) // 注册唤醒/解锁通知 workspaceNotificationCenter.addObserver( self, selector: #selector(wakeListener(_:)), name: NSWorkspaceDidWakeNotification, object: nil ) } @objc func sleepListener(_ notification: Notification) { print("系统即将锁屏/进入睡眠!") // 这里写你的业务逻辑 } @objc func wakeListener(_ notification: Notification) { print("系统已唤醒/解锁!") // 这里写你的业务逻辑 } func applicationWillTerminate(_ aNotification: Notification) { // 可选:App退出时移除监听,养成好习惯 NSWorkspace.shared.notificationCenter.removeObserver(self) } }
如果是Objective-C项目,对应的代码是这样的:
#import "AppDelegate.h" @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSNotificationCenter *workspaceCenter = [[NSWorkspace sharedWorkspace] notificationCenter]; // 注册睡眠通知 [workspaceCenter addObserver:self selector:@selector(sleepListener:) name:NSWorkspaceWillSleepNotification object:nil]; // 注册唤醒通知 [workspaceCenter addObserver:self selector:@selector(wakeListener:) name:NSWorkspaceDidWakeNotification object:nil]; } - (void)sleepListener:(NSNotification *)notification { NSLog(@"系统即将锁屏/进入睡眠!"); } - (void)wakeListener:(NSNotification *)notification { NSLog(@"系统已唤醒/解锁!"); } - (void)applicationWillTerminate:(NSNotification *)aNotification { [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self]; } @end
四、关于IORequestIdle的小提示
用IORequestIdle触发系统空闲时,要注意:
- 确保系统节能设置里的“电脑进入睡眠”时间是合理的,比如不要设成“永不”
- 有些第三方工具(比如防休眠的软件)会阻止系统进入睡眠,这时候
IORequestIdle可能不会生效,需要关闭这类工具测试
内容的提问来源于stack exchange,提问作者Antoine
相关产品推荐
相关产品推荐

