views:

166

answers:

3
- (void)launchSearch 
{
 EventsSearchViewController *searchController = [[EventsSearchViewController alloc] initWithNibName:@"EventsSearchView" bundle:nil];
 [self.navigationController pushViewController:searchController animated:YES];
 //[searchController release]; 
}

Notice the [searchController release] is commented out. I've understood that pushing searchController onto the navigation controller retains it, and I should release it from my code. I did just alloc/init it, after all, and if I don't free it, it'll leak.

With that line commented out, navigation works great. With it NOT commented out, I can navigate INTO this view okay, but coming back UP a level crashes with a *** -[CFArray release]: message sent to deallocated instance 0x443a9e0 error.

What's happening here? Is the NavigationController releasing it for me somehow when it goes out of view?

The boilerplate that comes on a UINavigationController template in XCode has the newly-pushed controller getting released. But when I do it, it fails.

---EDIT----

So this morning, I sit down, and it works. No real clue why. Sigh.

Taking what I thought I learned, then, and applying it to another piece of this same controller, I did the following. Yesterday I had this code WITHOUT the release statements, because it didn't work right with them. So this morning I added them to create:

- (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) {
        tableController = [[EventsTableViewController alloc]
            initWithNibName:@"EventsTableView" bundle:nil];
            [mainView addSubview:tableController.view];
            [tableController release];
    }

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

With it set up like this, when I come onto the view, the main portal of my view is filled with the EventsTableViewController's view, I can click to mapView and calendarView, but when I go BACK to tableView, I die because the table delegate methods are being called on a deallocated instance.

So I went and made all of these controllers into synthesized properties, so I can release them in [dealloc]. Which seems to work, but the real question is why adding these views as subviews doesn't retain them, passing ownership to the new view it's a member of, allowing me to release them right there?

A: 

I'd guess the fault lies in EventsSearchViewController's init. Is it returning an autoreleased self by mistake ?

Andiih
Only if its `[super init]` is. I haven't overridden its init methods.I should also note, this isn't the only ViewController this is happening with. I have other places in this app where if I explicitly release controllers after pushing them onto the navigation controller, I get calls to missing objects later.
Dan Ray
I presume you are not using searchController elsewhere in your code ? Once the navigationController returns it would be invalid.
Andiih
Nope, this is the only place.
Dan Ray
well there is nothing wrong with the 3 lines of code you posted (assuming you put the release back) so the fault is elsewhere in your project. Post more - I'll take a look.
Andiih
Thanks--I'll look around when I get in tomorrow. Any part that I ought to be looking in? Maybe the place in the root view controller where the navigationcontrol business is set up?
Dan Ray
That's plausible. But i'd start with the dealloc method of your view controllers: there should be nothing in there other than [blah release]; and then [super dealloc]; following on from that I'd look for some systematic abuse of properties. I've just written this then seen what Tom has written above - I totally agree with him!
Andiih
A: 

Looks like EventsSearchViewController is allocating an array and then over-releasing it, with one of the releases probably in its dealloc.

If you comment out the release, your EventsSearchViewController is never deallocated (it leaks). So, errors that occur as a result of its own dealloc will be masked since that method won't be called. Releasing the controller is the right thing, but you have another bug in the controller itself that only appears at dealloc time.

It could also be that dealloc is releasing an autoreleased array, so you may not have two explicit release calls in your code. But it looks very much like releasing something in dealloc that's causing the problem.

Tom Harrington
I threw you a fake with the array business. Turns out that the array in question was being used in that controller, and I was just doing something silly with it.
Dan Ray
+1  A: 

Wow, guys. Thanks so much for all your responses--tragically I sent you all on a horrible goosechase.

My NavigationView navigates a NSArray of Event objects (local arts events). My table view drills down to a detail view.

My detail view has in it the following:

-(void)loadEvent:(Event *)event
{
    thisEvent = event;          
}

And I call that from my table view before pushing the detail view onto the nav stack. thisEvent is a synthesized property of type Event, and so since it's synthesized, I dutifully release'd it in [dealloc].

Many of you already see the problem. Backing up to the table view, when I scroll such that the one I just saw is displayed, it builds the custom table row, and so it goes to get the title property from the Event.... which I just released inside the detail controller. Boom.

I added a retain to that loadEvent: method above and the crashes, they are gone.

NONE of this was really about the views getting retained and released by the navcontroller. It was about accidentally over-releasing the data objects I'm navigating. Part of what had me discover this was, I NSLogged myself in the [dealloc] of each of these view controllers, and I can now see they're behaving exactly as they should.

Thanks! I SO love this site.

Dan Ray