Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Darkroom

Guest
Original poster
Dec 15, 2006
2,445
0
Montréal, Canada
i'm recently researching ways to disable dimming, screen saver and sleep while an app is in full screen, and this is what i've discovered:

Code:
- (void)preventSleep
{
     keepAwakeTimer = [[NSTimer scheduledTimerWithTimeInterval:30  
target:self selector:@selector(stayAwake:) userInfo:nil repeats:  
YES] retain];
}
- (void)stayAwake:(NSTimer *)sleepTimer
{
    UpdateSystemActivity(OverallAct);// This is from Apple Tech Note  
QA1160:Preventing Sleep
}

i've noticed that the keepAwakeTimer is retained, and will fire off ever 30 seconds... does that mean that every 30 second the app will allocate memory without releasing it?
 

Sayer

macrumors 6502a
Jan 4, 2002
981
0
Austin, TX
There's a better way than running a timer every 30 seconds.

You should register for Power Management events and when the system wants to go to sleep you simply deny it. This way your app isn't constantly running wasting CPU time or potentially leaking memory.

Here's what I did (note this is in the main.m file):

Code:
#import <Cocoa/Cocoa.h>
#import <mach/mach_port.h>
#import <mach/mach_interface.h>
#import <mach/mach_init.h>

#import <IOKit/pwr_mgt/IOPMLib.h>
#import <IOKit/IOMessage.h>

io_connect_t		root_port;
IONotificationPortRef	notify;
io_object_t 		anIterator;

void callback(void * x,io_service_t y,natural_t messageType,void * messageArgument)
{
    printf("messageType %08lx, arg %08lx\n",(long unsigned int)messageType, (long unsigned int)messageArgument);
    
    switch ( messageType ) {
    case kIOMessageSystemWillSleep:
        IOAllowPowerChange(root_port,(long)messageArgument);
        printf("Going to sleep now\n");
        break;
    case kIOMessageCanSystemSleep: // we don't want to automatically go to sleep
        IOCancelPowerChange(root_port,(long)messageArgument);
        break;
    case kIOMessageSystemHasPoweredOn:
        printf("Just had a nice snooze\n");
        break;
	default:
		break;
    }
    
} /* callback */

int main(int argc, char *argv[])
{


    fprintf(stderr, "\nAttempting to register for system power notifications\n");
    root_port = IORegisterForSystemPower (0,&notify,callback,&anIterator);
    if ( root_port == MACH_PORT_NULL ) {
            fprintf(stderr, "IORegisterForSystemPower failed\n");
            return 1;
    }
        fprintf(stderr, "Registration successful\n");
    
    CFRunLoopAddSource(CFRunLoopGetCurrent(),
                        IONotificationPortGetRunLoopSource(notify),
                        kCFRunLoopDefaultMode);
	
    return NSApplicationMain(argc, (const char **) argv);
}

void closeIOKit() {

	kern_return_t result;
	
	result = IODeregisterForSystemPower(&anIterator);
	IOServiceClose(root_port);
	IOObjectRelease(anIterator);
	
	if (result == kIOReturnSuccess )
		fprintf(stderr, "Deregistration successful\n");

}

Note that with this code the system will go to sleep if the user explicitly tells it to e.g. presses the power button or selects any Sleep option in the UI.

There really isn't any way to cancel the user telling the system to go to sleep except maybe with the Kiosk APIs and/or disabling key combos/menus.

To properly close down the Mach port on app quit I use this in the app controller class:

Code:
- (void)applicationWillTerminate:(NSNotification *)notification {

	[self adShowExitFullScreenMode];

	closeIOKit();
}
 

kpua

macrumors 6502
Jul 25, 2006
294
0
While the above reply is a better solution for what you want to do, to answer your original question, the answer is yes UNLESS you invalidate/release the timer at some point (i.e. app termination). Of course, leaks at the end of the app's life are not a huge deal, since the OS reclaims the memory anyway, but it's still good practice to eliminate those kind of leaks as well.
 

luckylefty01

macrumors member
Apr 8, 2008
32
0
i'm recently researching ways to disable dimming, screen saver and sleep while an app is in full screen, and this is what i've discovered:

Code:
- (void)preventSleep
{
     keepAwakeTimer = [[NSTimer scheduledTimerWithTimeInterval:30  
target:self selector:@selector(stayAwake:) userInfo:nil repeats:  
YES] retain];
}
- (void)stayAwake:(NSTimer *)sleepTimer
{
    UpdateSystemActivity(OverallAct);// This is from Apple Tech Note  
QA1160:Preventing Sleep
}

i've noticed that the keepAwakeTimer is retained, and will fire off ever 30 seconds... does that mean that every 30 second the app will allocate memory without releasing it?

I think the question is how often you're calling the preventSleep method. I'm guessing you're calling that method only once, after which you just call the keepAwakeTimer method when you need it. In that case keepAwakeTimer should only be retained once (when you call preventSleep). If you do call -preventSleep more than once that you need to make sure to release the current instance of keepAwakeTime before assigning the new one.

And then you should call [keepAwakeTimer release] in dealloc.

One way to test this would be to set a breakpoint on the line with retain and see how many times that line gets hit.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.