views:

63

answers:

1

Odd problem in an iPhone app.

My application's main view is View A, which is a tab controller. One tab in particular is set to load View B. View B, when you click a button, modally displays View C. View C in turn has a button that, when pressed, sends a message to its delegate (View B's view controller), and the delegate then dismisses View C.

Now, my understanding is that View A is always holding a reference to View B. Yes?

Here's the sequence:

  1. Select tab to display view B.
  2. Press button to display view C (modal).
  3. Press button to dismiss - view C sends message, view B's controller does the dismissing. View B is now displayed.
  4. Repeat steps 2-3 TWICE MORE.
  5. View B's view controller deallocates (I have an NSLog in the dealloc so I know this is happening). The view is still displayed.
  6. Press button to display view C, get "EXC_BAD_ACCESS" because View B's view controller has been deallocated, so the button's "click" message has nowhere to go.

There are no memory warnings occurring at any time - I've put NSLog's in to make sure of it. View A and View B are both constructed in Interface Builder, not in code, and there is absolutely no code I've written that will call View B's dealloc method.

This always happens after EXACTLY three repetitions.

For reference, the buttons themselves are programmatically constructed in View B's viewWillAppear method. Here's the snippet:

    // create button
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(column*100+24, row*80+10, 64, 64);
    [button setImage:thumb forState:UIControlStateNormal];
    [button addTarget:self 
                    action:@selector(buttonClicked:) 
        forControlEvents:UIControlEventTouchUpInside];

So the button is supposed to send the "buttonClicked" message to View B's view controller. Works great for the first three times, stops working after the view controller mysteriously deallocates.

View B should never deallocate, as it is a top-level view displayed within the application's tab bar.

Any idea whatsoever on where I can start troubleshooting this?

Edit: Fun trivia. I added a [self retain] to View B's viewDidLoad, which should increase the retention count on the object. It does: I can now do the above process FOUR times before I get the EXC_BAD_ACCESS. I'm running with NSZombiesEnabled, so I know that it's View B's controller that's getting deallocated. I just have to figure out WHERE its retain count is being decremented since I didn't actually write any code that does so.

I know View A should have incremented View B's retention count; when View B subsequently displays View C modally, that shouldn't decrement the count, should it?

+1  A: 

Can't say without seeing code but if I to guess:

  1. In step three when you dismiss view-controller C, instead of releasing view-controller C, you accidentally release B. It takes a while for the error to show up because B has several retains on it from other objects. However, each time you release C, you decrement the release count until it hits zero.
  2. You have a custom accessor somewhere, such a C's delegate property, that sends a release to B when accessed. Same pattern as (1).

I suggest you do a project search on release and check all releases to see if any have B. There should be no explicit releases of B in the standard setup.

You could also override B's release method to log when it gets release (don't forget to call super) that will show you when the releases are happening which will give you an idea of where they are happening.

TechZen