Search code examples
objective-ciosios4

The NSTimer that doesn't invalidate (or a weird memory problem I can't solve)


I'm having a huge problem with the NSTimer object. I can't explain myself this behavior, and I will try to explain as best as I can.

I have a function in my view which is called placeAdvertisement. In this function there are multiple operations with static methods that uses as parameter one of my objects (another view):

if (self.adsController == nil) {
    self.adsController = [[AdsController alloc] ...];
    [self.view addSubView: self.adsController.view;
}

if (banner != nil) {

    self.adsController.banner = banner;
    [self.adsController updateBanner];

    //If a previous timer is still working (because this method can be called multiple times) invalidate
    if (self.adsTimer != nil)
        [self.adsTimer invalidate];

    [Advertisement operation1: self.adsController];
    [Advertisement operation2: self.adsController];

    self.adsTimer = [NSTimer scheduledTimerWithTimeInterval: 5 ...];

}

The last timer calls to another function, called quitAdvertisement, but he never gets called (when the failure is produced). The code seems to work well in normal conditions, the advertisement controller works correctly, the banner is placed and the timer calls adsTimer, which quits the banner.

The problem appears if a pop the view (returning back) and the push another one again. Once the view is loaded I push a button that fires the code placed before. The code executes well, but in "the middle" of the execution, in [Advertisement operation1: self.adsController] appears EXC_BAD_ACCESS:

[MyController AdvertisementController]: message sent to deallocated instance 0x4e9b420

It's like in the middle of the code, my object gets deallocated. I don't have any code that calls release of the object, just the dealloc, which has not been called for this instance of the view (Has been called for the previous view, which was popped up).

How can be this possible? Is there any way to debug that in better conditions?

I've used NSZombieEnabled.

Thanks!

***Little edit for the comments***

  1. AdsController is allocated like:

    self.adsController = [[AdsController alloc] initWithNibName:nil bundle:nil];

After in dealloc method:

[self.adsController release];

[super dealloc];
  1. Respect to the timer:

    It is allocated with repeat NO. After in dealloc:

    if (self.adsTimer != nil) [self.adsTimer invalidate];

Is this correct?


Solution

  • Just to clarify what was the problem.

    There was one NSNotification that was beign pushed only if the timer was active. This led me to believe that the problem was in the timer, but was the notification beign captured by a form that was released.

    So, it's important to be very carefully removing the observer from any notification when a form is poped out.

    I just want to thank your help.