實(shí)現(xiàn)Mac端App的功能:a.睡眠和喚醒的通知、b.實(shí)現(xiàn)‘App防睡眠’
(創(chuàng)建橋接頭文件)
參考:
Registering and unregistering for sleep and wake notifications
用IOKit阻止Mac進(jìn)入睡眠模式
Developer 開發(fā)者文檔 — Documentation Archive
Cocoa可以用來接收睡眠和喚醒的通知,而I/O Kit還可以防止或延遲 閑置睡眠(idle sleep)。然而,即使有I/O Kit,也不可能防止強(qiáng)制睡眠(forced sleep),只能延遲它。
注意: Mac OS X有兩種不同的情況下睡眠 — 強(qiáng)制(forced)和閑置(idle)。
- 當(dāng)用戶采取某種直接行動(dòng)讓機(jī)器進(jìn)入睡眠狀態(tài)時(shí),就會(huì)發(fā)生強(qiáng)制睡眠。合上筆記本電腦的蓋子或從蘋果頂部菜單欄中選擇'睡眠'都會(huì)導(dǎo)致強(qiáng)制睡眠。該系統(tǒng)還將在某些條件下誘導(dǎo)強(qiáng)制睡眠,例如熱緊急情況或電池電量不足。
- 閑置睡眠是閑置一段時(shí)間發(fā)生的,是機(jī)器閑置的一段時(shí)間內(nèi)配置的節(jié)能系統(tǒng)首選項(xiàng)。
本文只實(shí)現(xiàn)了OC代碼的睡眠/喚醒的通知使用、‘App防睡眠’方法!
關(guān)于相應(yīng)C語言的實(shí)現(xiàn),具體可以參考《Registering and unregistering for sleep and wake notifications》~
注冊(cè)/注銷 睡眠和喚醒的通知
-(void)OC_registerNotications { //OC-注冊(cè)通知
//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 {//睡眠的響應(yīng)
NSLog(@"receiveSleepNote: %@", [note name]);
}
-(void)receiveWakeNote:(NSNotification *)note { //喚醒的響應(yīng)
NSLog(@"receiveWakeNote: %@", [note name]);
}
實(shí)現(xiàn)‘App防睡眠’功能 :打開Mac App時(shí),不進(jìn)入睡眠模式!
頭文件:#import <IOKit/pwr_mgt/IOPMLib.h>
實(shí)現(xiàn)代碼如下:
// 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允許應(yīng)用程序返回一個(gè)簡短的字符串給用戶,解釋為什么該應(yīng)用程序阻止了睡眠。
2.關(guān)于AssertionType參數(shù) —— kIOPMAssertionType...
用kIOPMAssertionTypeNoDisplaySleep 防止顯示器睡眠(會(huì)防止系統(tǒng)睡眠);
用kIOPMAssertionTypeNoIdleSleep 防止系統(tǒng)睡眠(顯示器會(huì)睡眠)。測試結(jié)果是:
用kIOPMAssertionTypeNoDisplaySleep 既能防止顯示器睡眠又能防止系統(tǒng)睡眠,就像放視頻或做幻燈片一樣。
封裝 (根據(jù)個(gè)人需求)
將兩個(gè)方法都集成到一個(gè)OC類(MacSleepWakeObject)里面:均使用類方法執(zhí)行相關(guān)操作~
(?? 嫌棄在Swift中找相應(yīng)IPA — 防止系統(tǒng)睡眠使用I/O Kit時(shí)有使用C語言的方法,翻譯成Swift有點(diǎn)麻煩! 所以還是用OC類來進(jìn)行橋接~)
.h文件:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MacSleepWakeObject : NSObject
+(void)preventSystemSleep;//防止系統(tǒng)休眠
+(void)OC_registerNotications;//OC-注冊(cè)通知
+(void)OC_removeNotifications;//OC-移除通知
@end
NS_ASSUME_NONNULL_END
.m文件:
#import "MacSleepWakeObject.h"
#import <IOKit/pwr_mgt/IOPMLib.h>//防止休眠
@import Cocoa;//才可以 注冊(cè)、移除通知
@implementation MacSleepWakeObject
//防止系統(tǒng)休眠
+(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-注冊(cè)通知
//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 {//睡眠的響應(yīng)
NSLog(@"receiveSleepNote: %@", [note name]);
}
+(void)receiveWakeNote:(NSNotification *)note { //喚醒的響應(yīng)
NSLog(@"receiveWakeNote: %@", [note name]);
}
@end
手動(dòng)創(chuàng)建 橋接頭文件:
創(chuàng)建新文件時(shí)選擇'Header File'項(xiàng)創(chuàng)建一個(gè)頭文件,以'-Brigding-Header.h'結(jié)尾的格式命名(命名為"SwiftAndOC-Brigding-Header.h")!


在該工程中找到該TARGET,在'Build Settings'中找到'Objective-C Bridging Header'項(xiàng)!并輸入“${SRCROOT}/MacSleepWake/SwiftAndOC-Brigding-Header.h”——?jiǎng)?chuàng)建好橋接關(guān)系!


即創(chuàng)建好了橋接關(guān)系~
創(chuàng)建好了橋接關(guān)系之后,將該類(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()//防止系統(tǒng)休眠
MacSleepWakeObject .oc_registerNotications()//OC-注冊(cè)通知
//DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 30.0) {//延時(shí)30s
//MacSleepWakeObject .oc_removeNotifications()//OC-移除通知
//}
}
以上便是關(guān)于“實(shí)現(xiàn)Mac端App的功能(a.睡眠和喚醒的通知、b.實(shí)現(xiàn)‘App防睡眠’)”的討論~
關(guān)于更多的macOS系統(tǒng)狀態(tài)相關(guān)討論,請(qǐng)參考《macOS系統(tǒng)的狀態(tài)切換及其響應(yīng)方法》!
關(guān)于NSApp對(duì)應(yīng)的App狀態(tài)討論,請(qǐng)參考《NSApp — App狀態(tài)及其通知》!