Question

I'm trying to implement a timer but i'm getting bad access...I didn't use release neither in dealloc.

.h 

   NSTimer *_timerAnimacao;

@property (nonatomic, retain) NSTimer *timerAnimacao;

.m 
@synthesize timerAnimacao = _timerAnimacao;

Here is where I call the timer.

  if(acondition)
       _timerAnimacao = [NSTimer scheduledTimerWithTimeInterval:0.06 target:self selector:@selector(changeTimeFilter:) userInfo:nil repeats:YES];
     else 
            _timerAnimacao = [NSTimer scheduledTimerWithTimeInterval:0.06 target:self selector:@selector(changeTimeFilterHide:) userInfo:nil repeats:YES];

the changeTimeFilter works fine...but changeTimeFilterHide is getting BAD Access.

-(void)changeTimeFilter:(NSTimer *)theTimer{

    if (tAnimacaoFilter<5) {
        [_tbFilters setFrame:CGRectMake(_tbFilters.frame.origin.x, _tbFilters.frame.origin.y, _tbFilters.frame.size.width, 58*tAnimacaoFilter)];
    }
    if(tAnimacaoFilter < 10) {
        tAnimacaoFilter++;
        [_tbFeeds setFrame:CGRectMake(_tbFeeds.frame.origin.x, _tbFeeds.frame.origin.y + (4.4*tAnimacaoFilter), _tbFeeds.frame.size.width, _tbFeeds.frame.size.height - (4.4*tAnimacaoFilter))];
        [imgBordaTbDireita setFrame:CGRectMake(imgBordaTbDireita.frame.origin.x, _tbFeeds.frame.origin.y - 4, imgBordaTbDireita.frame.size.width, imgBordaTbDireita.frame.size.height)];
        [imgBordaTbEsquerda setFrame:CGRectMake(imgBordaTbEsquerda.frame.origin.x, _tbFeeds.frame.origin.y, imgBordaTbEsquerda.frame.size.width, imgBordaTbEsquerda.frame.size.height)];
    }
    else {
        if(_timerAnimacao)
           [_timerAnimacao invalidate];
        [btnFilter setEnabled:YES];
    }
}

-(void)changeTimeFilterHide:(NSTimer *)theTimer{
    if (tAnimacaoFilter<5) {
        [_tbFilters setFrame:CGRectMake(_tbFilters.frame.origin.x, _tbFilters.frame.origin.y, _tbFilters.frame.size.width, (58*5) - (58*tAnimacaoFilter))];
    }
    if(tAnimacaoFilter < 10) {
        tAnimacaoFilter++;
        [_tbFeeds setFrame:CGRectMake(_tbFeeds.frame.origin.x, _tbFeeds.frame.origin.y - (4.4*tAnimacaoFilter), _tbFeeds.frame.size.width, _tbFeeds.frame.size.height + (4.4*tAnimacaoFilter))];
        [imgBordaTbDireita setFrame:CGRectMake(imgBordaTbDireita.frame.origin.x, _tbFeeds.frame.origin.y - 4, imgBordaTbDireita.frame.size.width, imgBordaTbDireita.frame.size.height)];
        [imgBordaTbEsquerda setFrame:CGRectMake(imgBordaTbEsquerda.frame.origin.x, _tbFeeds.frame.origin.y, imgBordaTbEsquerda.frame.size.width, imgBordaTbEsquerda.frame.size.height)];
    }

    else {
        if(_timerAnimacao)
            [_timerAnimacao invalidate];
        [btnFilter setEnabled:YES];
    }
}
Was it helpful?

Solution

What you need to do on invalidate is to set NSTimer to nil like this:

[_timerAnimacao invalidate];
_timerAnimacao = nil;

If you don't do it your next commands will not work properly, e.g.:

if(_timerAnimacao)
  [_timerAnimacao invalidate];

Please note: if(_timerAnimacao) is the same like if(_timerAnimacao == nil) !

Take a look at this one as well: How do I use NSTimer?

OTHER TIPS

The instance of NSTimer needs to be in memory while you start and invalidate.

You can do that in two ways:

  1. Set the NSTimer as a property of Appdelegate class, and use it wherever you need to.

    NSTimer *timer=[(MyAppDelegate *)[[UIApplication sharedApplication] delegate].timer;

  2. Create a new class and set NStimer as a property. Create a class method to return a singleton instance of the class.

    static MyClass *obj = NULL;

    • (MyClass *)instance { @synchronized(self) { if (obj == NULL) obj = [[self alloc] init]; }

      return(obj); }

I would prefer the second method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top