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

Mac锁屏/唤醒触发的事件是什么?为何监听NSNotification无响应?

解决Mac锁屏/唤醒的通知监听问题

嘿,我来帮你搞定这个困扰!先给你理清楚Mac锁屏/唤醒时的系统事件,再帮你排查为什么你的sleepListener没被调用。

一、Mac锁屏/唤醒会触发哪些系统事件?

系统会通过NSWorkspace的通知中心发送以下核心通知:

  • NSWorkspaceWillSleepNotification:系统即将进入睡眠(包括锁屏,因为手动或通过IORequestIdle触发的锁屏本质是触发系统空闲睡眠)
  • NSWorkspaceDidWakeNotification:系统完成唤醒/解锁
  • 如果你需要区分屏幕休眠和系统整体睡眠,还有这两个:
    • NSWorkspaceScreensDidSleepNotification:屏幕进入休眠状态
    • NSWorkspaceScreensDidWakeNotification:屏幕唤醒

二、你的sleepListener没被调用的常见原因

大概率是监听注册的方式不对,或者时机有问题,你可以逐一排查:

  1. 用错了通知中心:很多人会直接用NotificationCenter.default注册,但系统睡眠/锁屏通知是通过NSWorkspace.shared.notificationCenter发送的,用默认通知中心肯定收不到!
  2. 监听注册太晚:要确保在App启动完成时就注册监听,比如放在applicationDidFinishLaunching方法里,别等到后面才注册。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:10:02