views:

39

answers:

1

I am working on my first core data iPhone application. I am using a navigation controller, and the root view controller displays 4 rows. Clicking the first row takes me to a second table view controller. However, when I click the back button, repeat the row tap, click the back button again, and tap the row a third time, I get an error. I have been researching this for a week with no success.

I can reproduce the error easily:

  1. Create a new Navigation-based Application, use Core Data for storage, call it MyTest which creates MyTestAppDelegate and RootViewController.
  2. Add new UIViewController subclass, with UITableViewController and xib, call it ListViewController.
  3. Copy code from RootViewController.h and .m to ListViewController.h and .m., changing the file names appropriately. To simplify the code, I removed the trailing “_” from all variables.
  4. In RootViewController, I added #import ListViewController.h, set up an array to display 4 rows and navigate to ListViewController when clicking the first row.

In ListViewController.m, I added #import MyTestAppDelegate.h” and the following code:

- (void)viewDidLoad {
    [super viewDidLoad];

 if (managedObjectContext == nil) {
        managedObjectContext = [(MyTestAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
 }
    ..
}

The sequence that causes the error is tap row, return, tap row, return, tap row -> error. Sometimes the error is simply, "EXC_BAD_ACCESS" and other times it is as follows:

2010-10-04 20:42:06.990 MyTest[765:207] -[__NSCFTimer persistentStoreCoordinator]: unrecognized selector sent to instance 0x5d3fa50
2010-10-04 20:42:06.993 MyTest[765:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFTimer persistentStoreCoordinator]: unrecognized selector sent to instance 0x5d3fa50'
*** Call stack at first throw:
(
 0   CoreFoundation                      0x02561919 __exceptionPreprocess + 185
 1   libobjc.A.dylib                     0x026af5de objc_exception_throw + 47
 2   CoreFoundation                      0x0256342b -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
 3   CoreFoundation                      0x024d3116 ___forwarding___ + 966
 4   CoreFoundation                      0x024d2cd2 _CF_forwarding_prep_0 + 50
 5   CoreData                            0x0228a1ca +[NSEntityDescription entityForName:inManagedObjectContext:] + 42
 6   MyTest                              0x00003f6d -[ListViewController fetchedResultsController] + 187
 7   MyTest                              0x00003c2c -[ListViewController numberOfSectionsInTableView:] + 36
 8   UIKit                               0x00468ba8 -[UITableViewRowData(UITableViewRowDataPrivate) _updateNumSections] + 111
 9   UIKit                               0x00468934 -[UITableViewRowData invalidateAllSections] + 66
 10  UIKit                               0x00325550 -[UITableView(_UITableViewPrivate) _updateRowData] + 113
 11  UIKit                               0x0031e978 -[UITableView numberOfSections] + 39
 12  UIKit                               0x004b4bb6 -[UITableViewController viewWillAppear:] + 102
 13  MyTest                              0x000039d5 -[ListViewController viewWillAppear:] + 67
 14  UIKit                               0x0036b8d7 -[UINavigationController _startTransition:fromViewController:toViewController:] + 858
 15  UIKit                               0x00366329 -[UINavigationController _startDeferredTransitionIfNeeded] + 266
 16  UIKit                               0x0036d3a0 -[UINavigationController pushViewController:transition:forceImmediate:] + 876
 17  UIKit                               0x003661c3 -[UINavigationController pushViewController:animated:] + 62
 18  MyTest                              0x0000301b -[RootViewController tableView:didSelectRowAtIndexPath:] + 182
 19  UIKit                               0x00327718 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140
 20  UIKit                               0x0031dffe -[UITableView _userSelectRowAtIndexPath:] + 219
 21  Foundation                          0x00034cea __NSFireDelayedPerform + 441
 22  CoreFoundation                      0x02542d43 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
 23  CoreFoundation                      0x02544384 __CFRunLoopDoTimer + 1364
 24  CoreFoundation                      0x024a0d09 __CFRunLoopRun + 1817
 25  CoreFoundation                      0x024a0280 CFRunLoopRunSpecific + 208
 26  CoreFoundation                      0x024a01a1 CFRunLoopRunInMode + 97
 27  GraphicsServices                    0x02dc62c8 GSEventRunModal + 217
 28  GraphicsServices                    0x02dc638d GSEventRun + 115
 29  UIKit                               0x002c3b58 UIApplicationMain + 1160
 30  MyTest                              0x000021cc main + 102
 31  MyTest                              0x0000215d start + 53
 32  ???                                 0x00000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'
Program received signal:  “SIGABRT”.
Program received signal:  “SIGABRT”.
kill
quit

The error occurs after NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext]; when the managedObjectContext is synthesized for the third time. I appreciate your patience and your help, as this makes no sense to me.

ADDENDUM: I may have a partial solution. http://www.iphonedevsdk.com/forum/iphone-sdk-development/41688-accessing-app-delegates-managed-object-context.html

If I do not release the managedObjectContext in the .m file, the error goes away. Is that ok or will that cause me issues?

 - (void)dealloc {
    [fetchedResultsController release];
    // [managedObjectContext release];
    [super dealloc];
}
A: 

I think I have the answer, but I would appreciate validation. In the second view controller, I added the following code, as I noted above:

if (managedObjectContext == nil) {
        managedObjectContext = [(MyTestAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
 }

I notice that the retain count of managedObjectContext is 0 when enter the if statement and it is 2 when I exit the if statement. If I leave [managedObjectContext release]; in the dealloc function, the retain count of managedObjectContext at the end of dealloc goes from 1 to 0 as I navigate back and forward and then I get an error the third time I open the second view controller.

If I comment out [managedObjectContext release], then everything seems pretty stable. The retain count is always 2 at the end of the if statement and is always 2 at the end of the dealloc statement, and nothing crashes. It seems odd to me that I have to change the memory management, since I am not knowingly doing an alloc or copy, but maybe that is happening in the app delegate. So, did I stumble onto the correct solution by trial and error?

jon