в NSTimer возникает утечка

#iphone #objective-c #memory-leaks #subclass #nstimer

#iPhone #objective-c #утечки памяти #подкласс #nstimer

Вопрос:

Я использую подкласс в своем приложении, в котором я использую nstimer для обнаружения бездействия пользователя. Вот утечка, и она возникает при каждом нажатии. вот код моего класса

 - (void)sendEvent:(UIEvent *)event {
    [super sendEvent:event];
    isRootView=FALSE;
    // Only want to reset the timer on a Began touch or an Ended touch, to reduce the number of timer resets.
    NSSet *allTouches = [event allTouches];
    if ([allTouches count] > 0) {
        // allTouches count only ever seems to be 1, so anyObject works here.
        UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
        if (phase == UITouchPhaseBegan)
            [self resetIdleTimer];
    }

}

- (void)resetIdleTimer {

    if (idleTimer) 
    {
        if ([idleTimer isValid]) 
        {
            [idleTimer invalidate];
            //[idleTimer release];
            //idleTimer=nil;
        }
    }
    maxIdleTime = 60;
    if (!isRootView) 
    {
        idleTimer = [NSTimer scheduledTimerWithTimeInterval:maxIdleTime target:self selector:@selector(idleTimerExceeded) userInfo:nil repeats:NO];
        [idleTimer retain];
    }
    else {
        if ([idleTimer isValid])
        {
            [idleTimer invalidate];
            //[idleTimer release];
            //idleTimer = nil;
        }
        if ([resetTimer isValid]) {
            [resetTimer invalidate];
            resetTimer=nil;

        }
    }


}

- (void)idleTimerExceeded {

    alert=[[UIAlertView alloc] initWithTitle:@"Confirmation!" message:@"Would you like to continue placing the order ?" delegate:self cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
    alert.tag=100;
    [alert show];
    [alert release];
    resetTimer=[NSTimer scheduledTimerWithTimeInterval:maxIdleTime target:self selector:@selector(resetApplication) userInfo:nil repeats:NO] ;
}
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (alertView.tag==100 ) {
        if (buttonIndex==1) 
        {
            if ([resetTimer isValid]) {
                [resetTimer invalidate];
                resetTimer=nil;

            }
        }
        else {
            [self resetApplication];
        }
    }
}
-(void) resetApplication
{
    isRootView=TRUE;
    [alert dismissWithClickedButtonIndex:1 animated:YES];
    if ([resetTimer isValid]) 
    {
        [resetTimer invalidate];
        resetTimer=nil;
    }

    if (idleTimer)
    {
        [idleTimer invalidate];
        [idleTimer release];
        idleTimer = nil;
    }

    SushiTeriaAppDelegate *appDelegate=(SushiTeriaAppDelegate*)[[UIApplication sharedApplication] delegate];
    [appDelegate resetApp];

}


- (void)dealloc {
    [super dealloc];

    //[resetTimer release];

    [alert release];


}
  

Я сохранил этот таймер. Если не сохранить, то приложение выйдет из строя.

Пожалуйста, подскажите мне, как устранить эту утечку

shivam

Ответ №1:

Используйте присвоенное свойство для переменной timer. пример.

 NSTimer globalTimer;

@property (nonatomic, assigned) NSTimer globalTimer;
@synthesize globalTimer;
  

Теперь назначьте таймер для этой переменной и используйте как self.globalTimer.
Одна вещь заключается в том, что всегда присваивайте переменной nil после использования. Не выпускайте его другим способом, это приведет
произошел сбой вашего приложения.

Комментарии:

1. if ([idleTimer isValid]) в этой строке

2. это приводит к сбою приложения, когда я пытаюсь аннулировать таймер

Ответ №2:

Происходит то, что вы вызываете метод resetIdleTimer каждый раз, когда пользователь нажимает на экран. Это увеличивает количество сохранений в idleTimer каждый раз, потому что вы сохранили его. Причина сбоя вашего приложения, если вы не сохраняете, заключается в том, что вы получаете автоматически выпущенный объект NSTimer из метода класса NSTimer

 idleTimer=[NSTimer scheduledTimerWithTimeInterval:maxIdleTime target:self selector:@selector(idleTimerExceeded) userInfo:nil repeats:NO];
  

Это означает, что вы не можете использовать этот объект вне этого конкретного метода, как вы делаете в своем методе resetApplication. Теперь вы могли бы проверять количество сохранений каждый раз, когда сохраняете его, но это проблематично. Итак, что я предлагаю, это объявить idleTimer как свойство сохранения.

 @property (retain) NSTimer *idleTimer;
  

и синтезируйте его установщики и добытчики после реализации.

 @synthesize idleTimer;
  

теперь используйте

 self.idleTimer=[NSTimer scheduledTimerWithTimeInterval:maxIdleTime target:self selector:@selector(idleTimerExceeded) userInfo:nil repeats:NO];
  

и отключите idleTimer только в вашем dealloc.

Комментарии:

1. Но это подкласс, поэтому dealloc не будет вызываться, я прав?

2. подкласс чего? Я не могу до вас дозвониться. Не имеет значения, освобожден ли ваш объект или нет при вашем фактическом использовании. В любом случае, использование свойства для nstimer устранит любые возникающие утечки памяти.