在 macOS 的程序开发中, 经常需要知道系统一些状态的改变而去对程序 做出一定的处理! 比如收到系统睡眠, 唤醒, 切换用户, 屏幕关闭, 显示屏保等系统状态.
大部分的系统状态, 通过 "NSWorkspace .shared .notificationCenter" 来实现:
- NSWorkspace .shared .notificationCenter .addObserver(self, selector: #selector(methodWillSleepNotification), name: NSWorkspace.willSleepNotification, object: nil)
- NSWorkspace .shared .notificationCenter .addObserver(self, selector: #selector(methodDidWakeNotification), name: NSWorkspace.didWakeNotification, object: nil)
- NSWorkspace .shared .notificationCenter .addObserver(self, selector: #selector(methodScreensDidSleepNotification), name: NSWorkspace.screensDidSleepNotification, object: nil)
- NSWorkspace .shared .notificationCenter .addObserver(self, selector: #selector(methodScreensDidWakeNotification), name: NSWorkspace.screensDidWakeNotification, object: nil)
- NSWorkspace .shared .notificationCenter .addObserver(self, selector: #selector(methodWillPowerOffNotification), name: NSWorkspace.willPowerOffNotification, object: nil)
- NSWorkspace .shared .notificationCenter .addObserver(self, selector: #selector(methodSessionDidResignActiveNotification), name: NSWorkspace.sessionDidResignActiveNotification, object: nil)
- NSWorkspace .shared .notificationCenter .addObserver(self, selector: #selector(methodSessionDidBecomeActiveNotification), name: NSWorkspace.sessionDidBecomeActiveNotification, object: nil)
相应的响应方法:
- // 睡眠 //NSWorkspace.willSleepNotification
- @objc func methodWillSleepNotification () {
- print("methodWillSleepNotification")
- }
- // 从睡眠中唤醒 //NSWorkspace.didWakeNotification
- @objc func methodDidWakeNotification () {
- print("methodDidWakeNotification")
- }
- // 屏幕睡眠 //NSWorkspace.screensDidSleepNotification
- @objc func methodScreensDidSleepNotification () {
- print("methodScreensDidSleepNotification")
- }
- // 屏幕唤醒 //NSWorkspace.screensDidWakeNotification
- @objc func methodScreensDidWakeNotification () {
- print("methodScreensDidWakeNotification")
- }
- // 当用户注销或关机 //NSWorkspace.willPowerOffNotification
- @objc func methodWillPowerOffNotification () {
- print("methodWillPowerOffNotification")
- }
- // 被切换到另一用户 //NSWorkspace.sessionDidResignActiveNotification
- @objc func methodSessionDidResignActiveNotification () {
- print("methodSessionDidResignActiveNotification")
- }
- // 被切换回到当前用户 //NSWorkspace.sessionDidBecomeActiveNotification
- @objc func methodSessionDidBecomeActiveNotification () {
- print("methodSessionDidBecomeActiveNotification")
- }
对于某一些特殊系统状态 (如'屏保'/'锁定屏幕'等), 就需要 NSDistributedNotificationCenter(跨进程的通知) 来实现:
- // 对于某一些系统状态, 就需要以下的 DistributedNotificationCenter(跨进程的通知)来实现:
- DistributedNotificationCenter .default() .addObserver(self, selector: #selector(method_screenSaverDidStart), name: NSNotification.Name(rawValue: "com.apple.screensaver.didstart"), object: nil)
- DistributedNotificationCenter .default() .addObserver(self, selector: #selector(method_screenSaverWillStop), name: NSNotification.Name(rawValue: "com.apple.screensaver.willstop"), object: nil)
- DistributedNotificationCenter .default() .addObserver(self, selector: #selector(method_screenSaverDidStop), name: NSNotification.Name(rawValue: "com.apple.screensaver.didstop"), object: nil)
- DistributedNotificationCenter .default() .addObserver(self, selector: #selector(method_screenIsLocked), name: NSNotification.Name(rawValue: "com.apple.screenIsLocked"), object: nil)
- DistributedNotificationCenter .default() .addObserver(self, selector: #selector(method_screenIsUnlocked), name: NSNotification.Name(rawValue: "com.apple.screenIsUnlocked"), object: nil)
相应的响应方法:
- // 屏保开始 //"com.apple.screensaver.didstart"
- @objc func method_screenSaverDidStart() {
- print("method_screenSaverDidStart")
- }
- // 屏保将要结束 //"com.apple.screensaver.willstop"
- @objc func method_screenSaverWillStop() {
- print("method_screenSaverWillStop")
- }
- // 屏保结束 //"com.apple.screensaver.didstop"
- @objc func method_screenSaverDidStop() {
- print("method_screenSaverDidStop")
- }
- // 屏幕锁住 //"com.apple.screenIsLocked"
- @objc func method_screenIsLocked() {
- print("method_screenIsLocked")
- }
- // 屏幕解锁 //"com.apple.screenIsUnlocked"
- @objc func method_screenIsUnlocked() {
- print("method_screenIsUnlocked")
- }
书写好上面的代码后, 开始模拟情景测试~
A. 直接选择屏幕顶部菜单栏对应的'睡眠'项:
打印如下:
- methodWillSleepNotification
- methodScreensDidSleepNotification
- method_screenIsLocked
- method_screenIsUnlocked
- methodDidWakeNotification
- methodScreensDidWakeNotification
其中, 点击'睡眠'项后进行睡眠的打印:
- methodWillSleepNotification
- methodScreensDidSleepNotification
- method_screenIsLocked
重新唤醒后的打印:
- method_screenIsUnlocked
- methodDidWakeNotification
- methodScreensDidWakeNotification
B. 直接选择顶部菜单栏对应的'锁定屏幕'项:
打印如下:
- method_screenIsLocked
- method_screenIsUnlocked
其中, 点击'锁定屏幕'项后进行锁屏的打印:
method_screenIsLocked
重新输入该账户密码, 解锁屏幕后的打印:
method_screenIsUnlocked
'系统偏好设置'里面的'桌面与屏幕保护程序'和'节能'
C. 启动'屏幕保护程序': 需要选择相应的闲置时长
启动'屏幕保护程序', 需要选择相应的闲置时间
C-1. 自动弹出了屏幕保护, 但是系统还未进入休眠:
[一] , 在系统偏好设置的'节能'中设置为'永不'- 永远不进行休眠
当前'节能'中设置的时长为'永不'
[二] , 在系统偏好设置的'节能'中设置相应的放置时长 - 可以进行休眠
当前'节能'中设置的时长为'1 分钟'
[一] , 在系统偏好设置的'节能'中设置为'永不'-- 不管是 (已经被锁屏)需要输入用户解锁屏幕的密码,(还没有被锁屏)还不需要输入用户解锁屏幕的密码!
[二] , 在系统偏好设置的'节能'中设置为'1 分钟'-- 只是出现了屏幕保护 (系统还未休眠) 就激活电脑来退出了屏幕保护!
上面的情况[一] ,[二] , 打印都如下:
- method_screenSaverDidStart
- method_screenIsLocked
- method_screenSaverWillStop
- method_screenSaverDidStop
- method_screenIsUnlocked
其中, 自动弹出了屏幕保护的打印:
- method_screenSaverDidStart
- method_screenIsLocked
解锁屏幕后的打印:(不管是否需要重新输入该账户密码)
- method_screenSaverWillStop
- method_screenSaverDidStop
- method_screenIsUnlocked
C-2. 自动弹出了屏幕保护, 并再放置到系统睡眠(系统偏好设置的'节能'中, 设置相应的放置时长)
当前'节能'中设置的时长为'1 分钟'
[$-1]. 不需要重新输入该账户密码:
- method_screenSaverDidStart
- method_screenIsLocked
- methodScreensDidSleepNotification
- method_screenSaverWillStop
- method_screenSaverDidStop
- method_screenSaverWillStop
- method_screenSaverDidStop
- method_screenIsUnlocked
- methodScreensDidWakeNotification
[$-2]. 需要重新输入该账户密码:
- method_screenSaverDidStart
- method_screenIsLocked
- methodScreensDidSleepNotification
- method_screenSaverWillStop
- method_screenSaverDidStop
- method_screenSaverWillStop
- method_screenSaverDidStop
- methodScreensDidWakeNotification
- method_screenIsUnlocked
其中, 自动弹出了屏幕保护, 并再放置到系统睡眠
- method_screenSaverDidStart
- method_screenIsLocked
- methodScreensDidSleepNotification
解锁屏幕后的打印:
[$-1]. 不需要重新输入该账户密码
- method_screenSaverWillStop
- method_screenSaverDidStop
- method_screenSaverWillStop
- method_screenSaverDidStop
- method_screenIsUnlocked
- methodScreensDidWakeNotification
[$-2]. 需要重新输入该账户密码
- method_screenSaverWillStop
- method_screenSaverDidStop
- method_screenSaverWillStop
- method_screenSaverDidStop
- methodScreensDidWakeNotification
- method_screenIsUnlocked
更多系统状态相应响应方法的顺序 -- 根据你自己开发 App 的需求, 就自己试出其调用顺序再搭配使用吧~
OC 代码:
- [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(sleepMethod:) name:NSWorkspaceWillSleepNotification object:nil];
- // 其中能捕获到的状态有:
- //NSWorkspaceWillSleepNotification // 睡眠
- //NSWorkspaceDidWakeNotification // 从睡眠中唤醒
- //NSWorkspaceWillPowerOffNotification // 当用户注销或关机
- //NSWorkspaceSessionDidResignActiveNotification // 被切换到另一用户
- //NSWorkspaceSessionDidBecomeActiveNotification // 被切换回到当前用户
- //NSWorkspaceScreensDidSleepNotification // 屏幕睡眠
- //NSWorkspaceScreensDidWakeNotification // 屏幕唤醒
需要去实现其响应方法(sleepMethod:)~
对于某一些系统状态 (如'屏保'/'锁定屏幕'等), 就需要 NSDistributedNotificationCenter(跨进程的通知) 来实现:
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(screensaverStart:) name:@"com.apple.screensaver.didstart" object:nil];
- // 其中的通知名称可以是:
- //com.apple.screensaver.didstart // 屏保开始
- //com.apple.screensaver.willstop // 屏保将要结束
- //com.apple.screensaver.didstop // 屏保结束
- //com.apple.screenIsLocked // 屏幕锁住
- //com.apple.screenIsUnlocked // 屏幕解锁
同样需要去实现其响应方法(screensaverStart:)~
以上便是关于 macOS 系统状态的讨论~
关于 NSApp 对应的 App 状态讨论, 请参考《NSApp - App 状态及其通知》!
goyohol's essay
来源: http://www.jianshu.com/p/b95eac8203cd