will this cause memory leak?

Discussion in 'Mac Programming' started by Darkroom, Jul 6, 2008.

  1. Darkroom Guest


    Dec 15, 2006
    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:

    - (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?
  2. Sayer macrumors 6502a


    Jan 4, 2002
    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):

    #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:
            printf("Going to sleep now\n");
        case kIOMessageCanSystemSleep: // we don't want to automatically go to sleep
        case kIOMessageSystemHasPoweredOn:
            printf("Just had a nice snooze\n");
    } /* 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");
        return NSApplicationMain(argc, (const char **) argv);
    void closeIOKit() {
    	kern_return_t result;
    	result = IODeregisterForSystemPower(&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:

    - (void)applicationWillTerminate:(NSNotification *)notification {
    	[self adShowExitFullScreenMode];
  3. Darkroom thread starter Guest


    Dec 15, 2006
    Montréal, Canada
    does this also disable dimming and screen saver activity?
  4. kpua macrumors 6502

    Jul 25, 2006
    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.
  5. luckylefty01 macrumors member

    Apr 8, 2008
    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.

Share This Page