#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 устранит любые возникающие утечки памяти.