views:

81

answers:

2

I have a UINavigation scheme with a "welcome" page, a middle page, and a detail page.

In the middle page, there's a segmented controller that can swap the main body of that page between a table, a calendar, and a MKMapView, each implemented with their own view controller classes.

Today I implemented the MapView and its annotations and all of that. It's nice. And a detail disclosure on each callout takes you to the detail page just the same way as if you'd gotten there via the table. Lovely.

I also have a right-button-bar button that pushes in a "search" view. From there you can search the data I'm navigating. When it's done filtering the data (an array of objects I'm keeping in a data singleton), it makes the table reload its data, and calls my annotation-clearer-and-builder methods on the map view, and then pops itself out, so the "middle" page (including whatever view was in the guts of it) is back on the screen.

Problem is, if I go back and forth between the map and the search a couple times, any mention of the table view causes us to crash with: *** -[CALayer retain]: message sent to deallocated instance 0x710b810. (I obviously have NSZombies turned on.)

I put an NSLog in the dealloc method of my table view controller. That thing's never getting called. I don't know if we're ditching it behind the scenes for memory purposes, or if I'm leaking it and can't get my hands back on it, or what. I'm sort of at a loss about where to look. Any hints?

EDIT:

Here's the code where I swap in the controllers for the main view of my "middle" viewController:

- (IBAction)switchView:(id)sender
{
    UISegmentedControl *seg = (UISegmentedControl *)sender;
    NSInteger choice = [seg selectedSegmentIndex];

    NSArray *array = [mainView subviews];
    UIView *oldView = [array objectAtIndex:0];
    [oldView removeFromSuperview];

    if (choice == 0) {
        if (!self.tableController)
            self.tableController = [[EventsTableViewController alloc]
                    initWithNibName:@"EventsTableView" bundle:nil];
        [mainView addSubview:self.tableController.view];
    }

    if (choice == 1) {
        if (!self.calendarController)
            self.calendarController = [[EventsCalendarViewController alloc]
                        initWithNibName:@"EventsCalendarView" bundle:nil];
        [mainView addSubview:self.calendarController.view];
    }
    if (choice == 2) {
        if (!self.mapController)
            self.mapController = [[EventsMapViewController alloc]
                        initWithNibName:@"EventsMapView" bundle:nil];
        [mainView addSubview:self.mapController.view];
    }
}

Per Adam below, I am doing removeFromSuperview there. I tried sticking in a retain on oldView just before removing it, but that didn't help.

Thanks!

A: 

Are you using removeFromSuperview? Be aware it releases as well as removes from superview...

Adam Eberbach
Hm. I am. And, after doing that, might it take a little bit to have it actually dealloc? Because this really only happens after I run a search to update my source data, which is a bit memory-intensive. In other words, I remove from superview, but the view is sticking around until after the next time I do my search routine. Might that release that happens there still allow my view to stick around and then get deallocated the next time we need memory?
Dan Ray
I edited my question to add the "swapping main views" code.
Dan Ray
A: 

I found it. On my search view controller I passed in a reference to the UITableView on the previous view, so I could call refreshData on it after filtering my source data.

I set it as a property (nonatomic, assign), which seemed right, but then at dealloc time, I went right on ahead and said [theTableView release]. This is actually the second time I've had mysterious and long-standing bugs crop up because I over-released something. I plan to actually learn this time.

Dan Ray