4

I have a view controller that i'm trying to push onto the navigation stack. I create the controller with a local variable, set it up, then assign it to a property. Then if I release the variable, I get EXE_BAD_ACCESS. if I retain (or auto release) it leaks.

CustomTVC* controller = [[CustomTVC alloc]initWithStyle:UITableViewStyleGrouped];
controller.managedObjectContext = self.managedObjectContext;

self.tableViewControllerIvar = controller;

[self.navigationController pushViewController:self.tableViewControllerIvar animated:YES];
 //[controller autorelease]; or [controller release]; or nothing

Here is exactly what happens if I release

  1. The above code is fired from pushing an add button in the nav bar.
  2. the view is pushed and everything is fine. In the new view I can push more views in over and over with no problem...unless
  3. I go back to the root view of the navigation stack. (Which is where the above code is from).
  4. Now if I drill down again to the second view, then try to push another it crashes.

Edit: I have a feeling that something is going wrong when I push the third controller onto the stack. With the push, it's inserting a new object into the managed object context which is causing the fetchedresultscontroller to update the tableview. There may be a broken pointer in there somewhere. I'll play with it and post the results. –

Edit: 5/16

Getting this error message in the log

* -[CustomTVC controllerWillChangeContent:]: message sent to deallocated instance 0x187270

This only happens after I pop the CustomTVC off the stack (go back to the navigation root view controller) I can push and save all I want as long as I don't pop the CustomTVC.

Myron Slaw
  • 886
  • 9
  • 21

3 Answers3

2

Fixed it. Had to set the fetched results controllers delegate to nil in viewDidLoad.

- (void)dealloc
{
    self.fetchedResultsController.delegate = nil;
    [_fetchedResultsController release];
    [_managedObjectContext release];
    [super dealloc];
}

seems the culprit was(according to the zombie instruments):

[NSFetchedResultsController(private methods) _managedObjectContextDidChange:]

Edit(s): Finally took the time to figure out how to put code in here correctly (I'm lazy)

Myron Slaw
  • 886
  • 9
  • 21
  • So i'm guessing it's good practice to set delegates to nil to prevent this? – Myron Slaw May 18 '11 at 02:38
  • According to the [NSFetchedResultsController reference page](http://tinyurl.com/69m8lbp), NSFetchedResultsController's delegate is an 'assign' property, so not setting it to nil shouldn't cause a leak. Did you redeclare it to retain? The usual practice is that [objects shouldn't retain their delegates](http://tinyurl.com/6hput4n) in order to avoid retain cycles. – Caleb May 18 '11 at 04:10
  • Yes, it's always a good idea to set the delegates to `nil` on `dealloc`. You never know whether there's someone still retaining the object that has the delegate property (even if you do know, you might change that in the future and will forget that it might cause trouble). – DarkDust May 19 '11 at 08:28
  • Yeah it's funny, a couple of days ago, I saw a question on here that asked if delegates should be set to nil. Most of the answers/comments said that it didn't matter. – Myron Slaw May 19 '11 at 22:18
0

autorelease should get the job done. When you assign tableViewControllerIvar, you can just call [controller autorelease]. This should take care of that.

CustomTVC* controller = [[CustomTVC alloc]initWithStyle:UITableViewStyleGrouped];
controller.managedObjectContext = self.managedObjectContext;

self.tableViewControllerIvar = [controller autorelease];

[self.navigationController pushViewController:self.VCTVC animated:YES];

If you are still getting EXE_BAD_ACCESS, then something else must be going on. Have you absolutely confirmed that this code, when run more than once, is causing the bad access?

Ryan Wersal
  • 3,210
  • 1
  • 20
  • 29
  • I have a feeling that something is going wrong when I push the third controller onto the stack. With the push, it's inserting a new object into the managed object context which is causing the fetchedresultscontroller to update the tableview. There may be a broken pointer in there somewhere. I'll play with it and post the results. – Myron Slaw May 15 '11 at 22:19
-1

you are assigning controller to tableViewControllerIvar

 self.tableViewControllerIvar = controller;

and you are releasing controller, so you need to retain it in the above line

 self.tableViewControllerIvar = [controller retain];

and when you are done with your "tableViewControllerIvar" then just release it, you shall not get any leaks after that

  • 1
    Setting a property isn't the same thing as just setting the value of a pointer. It's call to a method that should handle retain counts appropriately for the property declaration. Code like your second line is almost always wrong; either the retain is causing a leak, or the tableViewControllerIvar declaration is wrong. – smorgan May 15 '11 at 04:23
  • 1
    Like I said, that's the wrong fix either way. If the property isn't a retained property, then the right fix is to make it one, not to have a property that claims not to be retained but is actually "owning" a retain count. – smorgan May 15 '11 at 13:07