Mac端App 睡眠和喚醒的通知、實(shí)現(xiàn)‘App防睡眠’


實(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")!

選擇'Header File'項(xiàng)
將其命名為"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)系

找到'Objective-C Bridging Header'項(xiàng)
輸入“${SRCROOT}/MacSleepWake/SwiftAndOC-Brigding-Header.h”

創(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)及其通知










goyohol's essay

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容