Mac端App 睡眠和唤醒的通知、实现‘App防睡眠’


实现Mac端App的功能:a.睡眠和唤醒的通知、b.实现‘App防睡眠’
(创建桥接头文件)

参考:
Registering and unregistering for sleep and wake notifications
用IOKit阻止Mac进入睡眠模式


Developer 开发者文档Documentation Archive




Cocoa可以用来接收睡眠唤醒通知,而I/O Kit还可以防止延迟 闲置睡眠(idle sleep)。然而,即使有I/O Kit,也不可能防止强制睡眠(forced sleep),只能延迟它。

注意: Mac OS X两种不同的情况下睡眠强制(forced)和闲置(idle)。

  • 当用户采取某种直接行动让机器进入睡眠状态时,就会发生强制睡眠合上笔记本电脑的盖子或从苹果顶部菜单栏选择'睡眠'都会导致强制睡眠。该系统还将在某些条件下诱导强制睡眠,例如热紧急情况电池电量不足
  • 闲置睡眠是闲置一段时间发生的,是机器闲置的一段时间内配置的节能系统首选项


本文只实现了OC代码的睡眠/唤醒通知使用、‘App防睡眠’方法!
关于相应C语言实现,具体可以参考《Registering and unregistering for sleep and wake notifications》~



注册/注销 睡眠和唤醒的通知

-(void)OC_registerNotications { //OC-注册通知
    //These notifications are filed on NSWorkspace's notification center, not the default
        // notification center. You will not receive sleep/wake notifications if you file
        //with the default notification center.
    [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(receiveSleepNote:) name:NSWorkspaceWillSleepNotification object:NULL];
    
    [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(receiveWakeNote:) name:NSWorkspaceDidWakeNotification object:NULL];
}
-(void)OC_removeNotifications { //OC-移除通知
    [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self name:NSWorkspaceWillSleepNotification object:NULL];
    [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self name:NSWorkspaceDidWakeNotification object:NULL];
}
-(void)receiveSleepNote:(NSNotification *)note {//睡眠的响应
    NSLog(@"receiveSleepNote: %@", [note name]);
}
-(void)receiveWakeNote:(NSNotification *)note { //唤醒的响应
    NSLog(@"receiveWakeNote: %@", [note name]);
}



实现‘App防睡眠’功能 :打开Mac App时,不进入睡眠模式!

头文件:#import <IOKit/pwr_mgt/IOPMLib.h>
实现代码如下:

// kIOPMAssertionTypeNoDisplaySleep prevents display sleep,
// kIOPMAssertionTypeNoIdleSleep prevents idle sleep
 
//reasonForActivity is a descriptive string used by the system whenever it needs
//  to tell the user why the system is not sleeping. For example,
//  "Mail Compacting Mailboxes" would be a useful string.
 
//  NOTE: IOPMAssertionCreateWithName limits the string to 128 characters.
CFStringRef reasonForActivity = CFSTR("Describle Activity Type");

IOPMAssertionID assertionID;
IOReturn success = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, reasonForActivity, &assertionID);
if (success == kIOReturnSuccess) {
    //Add the work you need to do without
    //  the system sleeping here.
    
    success = IOPMAssertionRelease(assertionID);
    //The system will be able to sleep again.
}

1.新旧IPA

  • 废弃的IPA:IOPMAssertionCreate(<#CFStringRef AssertionType#>, <#IOPMAssertionLevel AssertionLevel#>, <#IOPMAssertionID *AssertionID#>)
    使用提示信息:'IOPMAssertionCreate' is deprecated: first deprecated in macOS 10.6
  • 新的IPA:IOPMAssertionCreateWithName是Mac OS X 10.6雪豹中可用的新API。
    IOPMAssertionCreateWithName允许应用程序返回一个简短的字符串给用户,解释为什么该应用程序阻止了睡眠。


2.关于AssertionType参数 —— kIOPMAssertionType...
kIOPMAssertionTypeNoDisplaySleep 防止显示器睡眠(会防止系统睡眠);
kIOPMAssertionTypeNoIdleSleep 防止系统睡眠(显示器会睡眠)。

测试结果是:

kIOPMAssertionTypeNoDisplaySleep 既能防止显示器睡眠又能防止系统睡眠,就像放视频或做幻灯片一样。



封装 (根据个人需求)

两个方法集成到一个OC类(MacSleepWakeObject)里面:均使用类方法执行相关操作~
(😒 嫌弃在Swift中找相应IPA — 防止系统睡眠使用I/O Kit时有使用C语言的方法,翻译成Swift有点麻烦! 所以还是用OC类来进行桥接~)

.h文件:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface MacSleepWakeObject : NSObject

+(void)preventSystemSleep;//防止系统休眠

+(void)OC_registerNotications;//OC-注册通知
+(void)OC_removeNotifications;//OC-移除通知

@end

NS_ASSUME_NONNULL_END

.m文件:

#import "MacSleepWakeObject.h"

#import <IOKit/pwr_mgt/IOPMLib.h>//防止休眠

@import Cocoa;//才可以 注册、移除通知


@implementation MacSleepWakeObject

//防止系统休眠
+(void)preventSystemSleep {
    // kIOPMAssertionTypeNoDisplaySleep prevents display sleep,
    // kIOPMAssertionTypeNoIdleSleep prevents idle sleep
     
    //reasonForActivity is a descriptive string used by the system whenever it needs
    //  to tell the user why the system is not sleeping. For example,
    //  "Mail Compacting Mailboxes" would be a useful string.
     
    //  NOTE: IOPMAssertionCreateWithName limits the string to 128 characters.
    CFStringRef reasonForActivity = CFSTR("Describle Activity Type");
    
    IOPMAssertionID assertionID;
    IOReturn success = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, reasonForActivity, &assertionID);
    if (success == kIOReturnSuccess) {
        //Add the work you need to do without
        //  the system sleeping here.
        
        success = IOPMAssertionRelease(assertionID);
        //The system will be able to sleep again.
    }
}

+(void)OC_registerNotications { //OC-注册通知
    //These notifications are filed on NSWorkspace's notification center, not the default
        // notification center. You will not receive sleep/wake notifications if you file
        //with the default notification center.
    [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(receiveSleepNote:) name:NSWorkspaceWillSleepNotification object:NULL];
    
    [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(receiveWakeNote:) name:NSWorkspaceDidWakeNotification object:NULL];
}
+(void)OC_removeNotifications { //OC-移除通知
    [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self name:NSWorkspaceWillSleepNotification object:NULL];
    [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self name:NSWorkspaceDidWakeNotification object:NULL];
}
+(void)receiveSleepNote:(NSNotification *)note {//睡眠的响应
    NSLog(@"receiveSleepNote: %@", [note name]);
}
+(void)receiveWakeNote:(NSNotification *)note { //唤醒的响应
    NSLog(@"receiveWakeNote: %@", [note name]);
}


@end


手动创建 桥接头文件
创建新文件时选择'Header File'项创建一个头文件,以'-Brigding-Header.h'结尾的格式命名(命名为"SwiftAndOC-Brigding-Header.h")!

选择'Header File'项
将其命名为"SwiftAndOC-Brigding-Header.h"

在该工程中找到该TARGET,在'Build Settings'中找到'Objective-C Bridging Header'项!并输入“${SRCROOT}/MacSleepWake/SwiftAndOC-Brigding-Header.h”——创建好桥接关系

找到'Objective-C Bridging Header'项
输入“${SRCROOT}/MacSleepWake/SwiftAndOC-Brigding-Header.h”

创建好桥接关系~


创建好桥接关系之后,将该类(MacSleepWakeObject)引入桥接头文件("SwiftAndOC-Brigding-Header.h")中 — #import "MacSleepWakeObject.h"!就可以在Swift代码中使用该类(MacSleepWakeObject)的方法了:

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    
    MacSleepWakeObject .preventSystemSleep()//防止系统休眠
    
    MacSleepWakeObject .oc_registerNotications()//OC-注册通知
    //DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 30.0) {//延时30s
    //MacSleepWakeObject .oc_removeNotifications()//OC-移除通知
    //}
}






以上便是关于“实现Mac端App的功能(a.睡眠和唤醒的通知、b.实现‘App防睡眠’)”的讨论~
关于更多macOS系统状态相关讨论,请参考macOS系统的状态切换及其响应方法

关于NSApp对应的App状态讨论,请参考NSApp — App状态及其通知










goyohol's essay

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容