macos 如何以编程方式防止 Mac 进入睡眠状态?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5596319/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 07:55:53  来源:igfitidea点击:

How to programmatically prevent a Mac from going to sleep?

objective-cmacos

提问by user698769

Is there way to prevent a Mac from going to sleep programmatically using Objective-C? The I/O kit fundamentals section on Apple's dev site tells me that a driver gets notified of an idle / system sleep, but I can't find a way of preventing the system from sleeping. Is it even possible?

有没有办法防止 Mac 使用 Objective-C 以编程方式进入睡眠状态?Apple 开发站点上的 I/O 套件基础部分告诉我,驱动程序收到空闲/系统睡眠通知,但我找不到阻止系统睡眠的方法。甚至有可能吗?

I've come across some other solutions using Caffeine, jiggler, sleepless and even AppleScript, but I want to do this in Objective-C. Thanks.

我遇到过其他一些使用 Caffeine、jiggler、sleepless 甚至 AppleScript 的解决方案,但我想在 Objective-C 中做到这一点。谢谢。

回答by Anne

Here is the official Apple documentation (including code snippet):
Technical Q&A QA1340 - How to I prevent sleep?

这是 Apple 官方文档(包括代码片段):
技术问答 QA1340 - 如何防止睡眠?

Quote:Preventing sleep using I/O Kit in Mac OS X 10.6 Snow Leopard:

引用:在 Mac OS X 10.6 Snow Leopard 中使用 I/O Kit 防止睡眠:

#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("Describe 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. 
}

For older OSX version, check the following:
Technical Q&A QA1160 - How can I prevent system sleep while my application is running?

对于较旧的 OSX 版本,请检查以下内容:
技术问答 QA1160 - 如何在应用程序运行时防止系统休眠?

Quote:Example usage of UpdateSystemActivity (the canonical way for < 10.6)

引用:UpdateSystemActivity 的示例用法(< 10.6 的规范方式)

#include <CoreServices/CoreServices.h>

void
MyTimerCallback(CFRunLoopTimerRef timer, void *info)
{
    UpdateSystemActivity(OverallAct);
}


int
main (int argc, const char * argv[])
{
    CFRunLoopTimerRef timer;
    CFRunLoopTimerContext context = { 0, NULL, NULL, NULL, NULL };

    timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 30, 0, 0, MyTimerCallback, &context);
    if (timer != NULL) {
        CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes);
    }

    /* Start the run loop to receive timer callbacks. You don't need to
    call this if you already have a Carbon or Cocoa EventLoop running. */
    CFRunLoopRun();

    CFRunLoopTimerInvalidate(timer);
    CFRelease(timer);

    return (0);
}

回答by Graham Miln

Apple's Q&A1340replaces Q&A1160. The latest Q&A answers the question "Q: How can my application get notified when the computer is going to sleep or waking from sleep? How do I prevent sleep?"

Apple 的Q&A1340取代了 Q&A1160。最新的问答回答了“问:当计算机进入睡眠状态或从睡眠状态唤醒时,我的应用程序如何得到通知?如何防止睡眠?”的问题。

Listing 2 of Q&A1340:

Q&A1340的清单2 :

#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("Describe 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. 
}

Note that you can only stop idle time sleep, not sleep triggered by the user.

请注意,您只能停止空闲时间睡眠,不能停止用户触发的睡眠。

For applications supporting Mac OS X 10.6 and later, use the new IOPMAssertionfamily of functions. These functions allow other applications and utilities to see your application's desire not to sleep; this is critical to working seamlessly with third party power management software.

对于支持 Mac OS X 10.6 及更高版本的应用程序,请使用新的IOPMAssertion系列函数。这些函数允许其他应用程序和实用程序看到您的应用程序不想睡觉的愿望;这对于与第三方电源管理软件无缝协作至关重要。

回答by edc1591

Just create an NSTimer that fires a function with this

只需创建一个 NSTimer 来触发一个函数

UpdateSystemActivity(OverallAct);

I'm pretty sure that that's exactly what Caffeine does.

我很确定这正是咖啡因所做的。