实现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")!
在该工程中找到该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状态及其通知》!
网友评论