AddressBook API woes - NSInternalInconsistencyException - iphone

My situation is the following:
We're creating an application that (among other things) shows data from the Public Folders in Exchange. We'd like our iPhone App to display contacts like the iPhone does it by default (like Apple's AddressBook app), therefore we're making use of the AddressBook API. However, we don't intend to save any displayed contacts on the iPhone itself, it will just be used to display contacts in the Public Folders of Exchange.
When we're about to show a contact record, we make use of the 'pushViewController' method to display an 'ABUnknownPersonViewController'. In code we're creating ABRecordRef objects using the ABPersonCreate() method. Part of it works fine, I see the name and other details that are show in the header (next to the picture placeholder). However, once I add any details that are to be shown in a UITableViewCell layout (like phone, address, etc...) it doesn't show up. Worse still, the app crashes once I load a ABPersonViewController for the 2nd time and the 'setDisplayedPerson:' method is being called. Note: the first time it loads just fine, but it doesn't show the data that should be displayed in UITableViewCells.
I receive the following error message:
2010-08-10 16:23:21.624 SharepointApp[5058:207] *** Assertion failure in -[ABPersonTableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1261.5/UITableView.m:904
2010-08-10 16:23:21.627 SharepointApp[5058:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the
number of sections contained in the table view before the update (0), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).'
*** Call stack at first throw:
(
0 CoreFoundation 0x02b05919 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x02c535de objc_exception_throw + 47
2 CoreFoundation 0x02abe078 +[NSException raise:format:arguments:] + 136
3 Foundation 0x0019a8cf -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
4 UIKit 0x0041863e -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] + 7808
5 UIKit 0x004086d1 -[UITableView endUpdates] + 42
6 AddressBookUI 0x025a2016 -[ABPersonTableViewDataSource setCurrentTableHeaderView:] + 49
7 AddressBookUI 0x025a194d -[ABPersonTableViewDataSource updateTableHeaderView] + 928
8 AddressBookUI 0x025a2276 -[ABPersonTableViewDataSource setPersonModelController:] + 441
9 AddressBookUI 0x025ef9f0 -[ABPersonViewControllerHelper setDisplayedPeople:] + 307
10 AddressBookUI 0x025efbe5 -[ABPersonViewControllerHelper _updateDisplayedPeople] + 198
11 SharepointApp 0x0006866f -[WSPublicContactDetailViewController retrievePersonDataCompleted:] + 654
12 Foundation 0x0011ee9a __NSThreadPerformPerform + 251
13 CoreFoundation 0x02ae6d7f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
14 CoreFoundation 0x02a452cb __CFRunLoopDoSources0 + 571
15 CoreFoundation 0x02a447c6 __CFRunLoopRun + 470
16 CoreFoundation 0x02a44280 CFRunLoopRunSpecific + 208
17 CoreFoundation 0x02a441a1 CFRunLoopRunInMode + 97
18 GraphicsServices 0x0307b2c8 GSEventRunModal + 217
19 GraphicsServices 0x0307b38d GSEventRun + 115
20 UIKit 0x003adb58 UIApplicationMain + 1160
21 SharepointApp 0x00002878 main + 102
22 SharepointApp 0x000027e6 start + 54
23 ??? 0x00000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'
Here's part of my the code:
ABRecordRef person = ABPersonCreate();
if (person) {
ABRecordSetValue(person, kABPersonLastNameProperty, #"Schreurs", NULL);
ABRecordSetValue(person, kABPersonFirstNameProperty, #"Wolfgang", NULL);
ABRecordSetValue(person, kABPersonOrganizationProperty, #"Webstate", NULL);
ABMultiValueRef phone = ABMultiValueCreateMutable(kABStringPropertyType);
if (phone) {
ABMultiValueAddValueAndLabel(phone, #"06 123 432 23", kABPersonPhoneMobileLabel, NULL);
ABRecordSetValue(person, kABPersonPhoneProperty, phone, NULL);
CFRelease(phone);
}
[self setUnknownPersonViewDelegate:self];
[self setDisplayedPerson:person];
CFRelease(person);
}

I found the solution to this problem. Apparently it's not a good approach to create the person (ABRecordRef) object inside the view controller. Instead create the person before loading the ABUnknownViewController. Also call [setDisplayedPerson:] before loading the ABUnknownViewController. This way the rows and sections get correctly initialized, there won't be any inconsistency exceptions anymore.

Related

iOS crash 'NSInternalInconsistencyException', reason: 'statement is still active' Core Data cache related?

Very occasionally seeing these pop up in crash reports on screens using NSFetchedResultsController, and not sure how to address them. I don't believe I'm using threading anywhere, unless NSFetchedResults is using them internally.
'NSInternalInconsistencyException', reason: 'statement is still active' is the full explanation I get.
Two recent stack traces:
0 CoreFoundation 0x37a368bf __exceptionPreprocess + 163
1 libobjc.A.dylib 0x3151c1e5 objc_exception_throw + 33
2 CoreData 0x340b2ea5 -[NSSQLiteStatement cachedSQLiteStatement] + 1
3 CoreData 0x340b274f -[NSSQLiteConnection prepareSQLStatement:] + 55
4 CoreData 0x34156049 -[NSSQLChannel selectRowsWithCachedStatement:] + 61
5 CoreData 0x34181d63 newFetchedRowsForFetchPlan_MT + 783
6 CoreData 0x340bab07 -[NSSQLCore newRowsForFetchPlan:] + 351
7 CoreData 0x34160011 -[NSSQLCore fetchRowForObjectID:] + 1005
8 CoreData 0x340cca57 -[NSSQLCore newValuesForObjectWithID:withContext:error:] + 195
9 CoreData 0x340cbf83 _PFFaultHandlerLookupRow + 423
10 CoreData 0x340cba97 _PF_FulfillDeferredFault + 187
11 CoreData 0x340cb94f _sharedIMPL_pvfk_core + 39
12 PowerPro 0x0006a779 -[GuestCard getPrimaryProspectiveTenant] (GuestCard.m:77)
13 PowerPro 0x00017bf9 -[OutstandingFollowupsViewController configureCell:atIndexPath:] (OutstandingFollowupsViewController.m:208)
14 PowerPro 0x00017b9b -[OutstandingFollowupsViewController tableView:cellForRowAtIndexPath:] (OutstandingFollowupsViewController.m:203)
Last Exception Backtrace:
0 CoreFoundation 0x37a368bf __exceptionPreprocess + 163
1 libobjc.A.dylib 0x3151c1e5 objc_exception_throw + 33
2 CoreData 0x340b2ea5 -[NSSQLiteStatement cachedSQLiteStatement] + 1
3 CoreData 0x340b274f -[NSSQLiteConnection prepareSQLStatement:] + 55
4 CoreData 0x34156049 -[NSSQLChannel selectRowsWithCachedStatement:] + 61
5 CoreData 0x340c26eb -[NSSQLCore _newRowsForFetchPlan:selectedBy:withArgument:] + 515
6 CoreData 0x340bab3f -[NSSQLCore newRowsForFetchPlan:] + 407
7 CoreData 0x3415ea55 -[NSSQLCore newFetchedPKsForSourceID:andRelationship:] + 2217
8 CoreData 0x3416a935 -[NSSQLCore newValueForRelationship:forObjectWithID:withContext:error:] + 689
9 CoreData 0x34108f8b -[NSFaultHandler retainedFulfillAggregateFaultForObject:andRelationship:withContext:] + 479
10 CoreData 0x340dcb23 -[_NSFaultingMutableSet willRead] + 219
11 CoreData 0x340dc70b -[_NSFaultingMutableSet count] + 23
12 PowerPro 0x00016eb1 -[BrowseGuestCardsViewController configureCell:atIndexPath:] (BrowseGuestCardsViewController.m:246)
13 PowerPro 0x00017173 -[BrowseGuestCardsViewController tableView:cellForRowAtIndexPath:] (BrowseGuestCardsViewController.m:222)
14 UIKit 0x34e4e9cb -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] + 547
15 UIKit 0x34e4daa9 -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1077
16 UIKit 0x34e4d233 -[UITableView layoutSubviews] + 207
17 UIKit 0x34df1d4b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 183
18 CoreFoundation 0x3799522b -[NSObject performSelector:withObject:] + 43
19 QuartzCore 0x3318c381 -[CALayer layoutSublayers] + 217
20 QuartzCore 0x3318bf99 CA::Layer::layout_if_needed(CA::Transaction*) + 217
21 QuartzCore 0x3318bea5 -[CALayer layoutIfNeeded] + 153
22 UIKit 0x34eb6fe1 -[UIButton titleLabel] + 73
23 PowerPro 0x00017983 -[BrowseGuestCardsViewController viewDidLoad] (BrowseGuestCardsViewController.m:75)
It's more than likely that this is a threading problem in some way or another. There isn't quite enough information in the question to see for sure, but it's worth check through the crash logs and looking at the stack traces for all threads at the time of the exception, and see if any other threads are doing anything which interacts with a managed object. It could be that you have a notification handler, a URL connection completion handler, or some other bit of code using concurrency which you hadn't noticed, using core data objects in the background. It's worth noting that setting or accessing any property on any managed object from a context that's being used on more than one thread could potentially trigger this kind of exception, which can make it pretty tough to diagnose.
The relatively simple solution to solving these problems in most apps is to push the execution of that code to the main thread (using dispatch_async()). Alternatively, if you've got lots of processing to do it might be better to create a child context on the background thread and re-fetch the object from the child context, then save the child context. Of course, to re-fetch the object you need to have its objectID, which is a property which can only be accessed on the thread the object was originally fetched on…
Got this error while simultaneously requesting data with NSFetchedResultController (from main thread context) and NSFetchRequest through my background context.
The way I have handled this is by making each of my MOCs have its own persistent store coordinator. Both of the persistent store coordinators talk to the same persistent store on disk.

ABPeoplePicker Crash for Only One Person

I have an app that only crashes for one of my tester’s - no one else’s. But it crashes consistently for her. It’s very odd.
Details:
She has in iPhone 4 and an iPhone 3Gs
The app crashes on all OSes on BOTH phones
The app crashes with all contacts no matter how they were created
When she sends me her contacts they work fine on both my iPHone 4 and my 3G (not s)
She is the ONLY one that ever gets a crash and it is consistent across both phones and all OSes
She has uninstalled and reinstalled the app and the provisioning profile
She is syncing her iPhone with a windows machine version of iTunes
The crash happens when we use ABPeoplePicker.
From her perspective it looks like the minute she selects a phone number the app crashes.
Of course she is not in our app at that moment. She is in the ABPeoplePicker navigation view provided by Apple.
From the resymbolicated crash log it looks to me like it’s actually crashing when it is trying to return to our app. In other words I can’t find any mention of our app actually being responsible for the crash in the crash log (see below).
It looks like it’s not able to get the index of the selected phone number and then fails when trying to pop back into our app but that’s a guess at best.
I have read the Apple docs and tried to do due diligence in learning about how to read crash logs but I am still stumped.
Here are my questions:
1. Does anyone know what Exception Codes: 0x00000000, 0x00000000 means?
2. Am I correct in assuming that line 9 is where the actual issues is referred to? And if so how do I understand what objc_exception_throw + 64 means?
3. Can anyone shed some light on what this crash log says the problem is?
Incident Identifier:
CrashReporter Key:
Hardware Model: iPhone3,1
Process: My App [471]
Path:
Identifier: My App
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2010-12-06 16:32:44.088 -0600
OS Version: iPhone OS 4.0.2 (8A400)
Report Version: 104
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread: 0
Thread 0 Crashed:
0 libSystem.B.dylib 0x000791d0 __kill + 8
1 libSystem.B.dylib 0x000791c0 kill + 4
2 libSystem.B.dylib 0x000791b2 raise + 10
3 libSystem.B.dylib 0x0008d6fa abort + 50
4 libstdc++.6.dylib 0x00044a20 __gnu_cxx::__verbose_terminate_handler() + 376
5 libobjc.A.dylib 0x000059ec _objc_terminate + 104
6 libstdc++.6.dylib 0x00042df2 __cxxabiv1::__terminate(void (*)()) + 46
7 libstdc++.6.dylib 0x00042e46 std::terminate() + 10
8 libstdc++.6.dylib 0x00042f16 __cxa_throw + 78
9 libobjc.A.dylib 0x000048cc objc_exception_throw + 64
10 CoreFoundation 0x0001fb72 -[__NSArrayI objectAtIndex:] + 154
11 My App 0x00005a68 0x1000 + 19048
12 My App 0x00005dec 0x1000 + 19948
13 UIKit 0x000668f4 -[UIViewController view] + 104
14 UIKit 0x000784e4 -[UIViewController contentScrollView] + 16
15 UIKit 0x00078354 -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] + 24
16 UIKit 0x00078252 -[UINavigationController _layoutViewController:] + 18
17 UIKit 0x00077d58 -[UINavigationController _startTransition:fromViewController:toViewController:] + 372
18 UIKit 0x00077b68 -[UINavigationController _startDeferredTransitionIfNeeded] + 176
19 UIKit 0x00066fa8 -[UINavigationController pushViewController:transition:forceImmediate:] + 600
20 UIKit 0x00066d40 -[UINavigationController pushViewController:animated:] + 28
21 My App 0x0000a29a 0x1000 + 37530
22 My App 0x0000bcba 0x1000 + 44218
23 AddressBookUI 0x00032cfc -[ABPeoplePickerNavigationController personViewController:shouldPerformDefaultActionForPerson:property:identifier:withMemberCell:] + 152
24 AddressBookUI 0x0003b8ce -[ABPersonViewControllerHelper personTableViewDataSource:selectedPropertyAtIndex:inPropertyGroup:withMemberCell:forEditing:] + 222
25 AddressBookUI 0x0004a17c -[ABPersonTableViewDataSource valueAtIndex:selectedForPropertyGroup:withMemberCell:forEditing:] + 40
26 AddressBookUI 0x00048c00 -[ABPersonTableViewDataSource tableView:didSelectRowAtIndexPath:] + 316
27 UIKit 0x00091f40 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 656
28 UIKit 0x0009db40 -[UITableView _userSelectRowAtIndexPath:] + 124
29 Foundation 0x00086c86 __NSFireDelayedPerform + 362
30 CoreFoundation 0x00071a54 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 8
31 CoreFoundation 0x00073ede __CFRunLoopDoTimer + 854
32 CoreFoundation 0x0007485e __CFRunLoopRun + 1082
33 CoreFoundation 0x0001d8e4 CFRunLoopRunSpecific + 224
34 CoreFoundation 0x0001d7ec CFRunLoopRunInMode + 52
35 GraphicsServices 0x000036e8 GSEventRunModal + 108
36 GraphicsServices 0x00003794 GSEventRun + 56
37 UIKit 0x000062a0 -[UIApplication _run] + 396
38 UIKit 0x00004e10 UIApplicationMain + 664
39 My App 0x0000d694 0x1000 + 50836
40 My App 0x00002d00 0x1000 + 7424
Here is my ABPeoplePicker code.
#pragma mark ABPeoplePickerNavigationControllerDelegate methods
// Displays the information of a selected person
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
return YES;
}
// Does not allow users to perform default actions such as dialing a phone number, when they select a person property.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier {
CFStringRef cfName = ABRecordCopyCompositeName(person);
self.selectedName = [NSString stringWithString:(NSString *)cfName];
CFRelease(cfName);
ABMultiValueRef allThePhoneNums = ABRecordCopyValue(person, kABPersonPhoneProperty);
// ABMultiValueGetIndexForIdentifier the exact value of the "identifier" passed to us.
NSString *number = (NSString *)ABMultiValueCopyValueAtIndex(allThePhoneNums, ABMultiValueGetIndexForIdentifier(allThePhoneNums, identifier));
self.selectedNumber = number;
[number release];
CFRelease(allThePhoneNums);
[self showDialOutToPartViewControllerWithName:self.selectedName andNumber:self.selectedNumber];
[peoplePicker dismissModalViewControllerAnimated:YES];
return NO;
}
// Dismisses the people picker and shows the application when users tap Cancel.
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker; {
[self dismissModalViewControllerAnimated:YES];
}
Foremost, it helps to symbolicate your crash logs using the symbolicatecrash tool and the DSYM file that was generated when you compiled it. I won't discuss how to do that here -- you can search Google to find more details; try "symbolicate crash log DSYM" as keywords.
Once you do that, instead of:
My App 0x0232032+433
It will show something like this:
My App [className callSomeMethod:argument]
Much easier to find the line of code that is spawning the problem.
However - note in the stack trace that the last line of code is [array objectAtIndex:] in Foundation. This method will throw an NSRangeException when you pass an index outside of the bounds of the receiver (e.g. array). From the NSArray docs:
If index is beyond the end of the
array (that is, if index is greater
than or equal to the value returned by
count), an NSRangeException is raised.
So, I'd put my money on that being your crash.
Then the question is - after you symbolicate your crash log - what line of your code is calling an array with an out-of-bounds index?

iPhone - Multithreading in Tableview - feasible approach?

I have been tracking a nasty bug recently of which I knew it was occurring due to my multithreaded approach (I add the crashreport at the end).
In my App I load a UITableView and fill it with data I store using Coredata. This data in turn I retrieve from a webservice, thus it might take some time, depending on my connection.
Anyway, I have managed to track it down a little and I know the issue is because an array is empty though I thought it shouldn't be. Then, when
numberOfRowsInSection:(NSInteger)section
is called the program crashes - but only sometimes!!!
I was wondering how to debug this properly and my approach was to call
reloadData
on the tableView after the view finishes loading. But appearantly
- (void)viewDidLoad
but of course this didn't help. Is the correct way here to create another thread and have it check repeatadly whether the data is ready and prepared? Any suggestions/opinions?
2011-01-19 21:50:49.605 myApp[2017:307] *** Terminating app due to uncaught exception
'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array'
*** Call stack at first throw:
(
0 CoreFoundation 0x314d0987 __exceptionPreprocess + 114
1 libobjc.A.dylib 0x319a149d objc_exception_throw + 24
2 CoreFoundation 0x31462795 -[__NSArrayM objectAtIndex:] + 184
3 myApp 0x000092f7 -[MyTableViewController tableView:numberOfRowsInSection:] + 106
4 UIKit 0x33902bcf -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 1338
5 UIKit 0x33903529 -[UITableViewRowData(UITableViewRowDataPrivate) _ensureSectionOffsetIsValidForSection:] + 120
6 UIKit 0x33902645 -[UITableViewRowData numberOfRows] + 96
7 UIKit 0x3390207b -[UITableView noteNumberOfRowsChanged] + 82
8 UIKit 0x33901bff -[UITableView reloadData] + 582
9 UIKit 0x33904a0b -[UITableView _reloadDataIfNeeded] + 50
10 UIKit 0x33904e63 -[UITableView layoutSubviews] + 18
11 UIKit 0x338b10cf -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 26
12 CoreFoundation 0x3146ebbf -[NSObject(NSObject) performSelector:withObject:] + 22
13 QuartzCore 0x30a6c685 -[CALayer layoutSublayers] + 120
14 QuartzCore 0x30a6c43d CALayerLayoutIfNeeded + 184
15 QuartzCore 0x30a6656d _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 212
16 QuartzCore 0x30a66383 _ZN2CA11Transaction6commitEv + 190
17 QuartzCore 0x30a70e4f _ZN2CA11Transaction5flushEv + 46
18 QuartzCore 0x30a6db75 +[CATransaction flush] + 24
19 UIKit 0x338e803f -[UIApplication _reportAppLaunchFinished] + 30
20 UIKit 0x338d6317 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 462
21 UIKit 0x338a248b -[UIApplication handleEvent:withNewEvent:] + 1114
22 UIKit 0x338a1ec9 -[UIApplication sendEvent:] + 44
23 UIKit 0x338a1907 _UIApplicationHandleEvent + 5090
24 GraphicsServices 0x35d66f03 PurpleEventCallback + 666
25 CoreFoundation 0x314656ff __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
26 CoreFoundation 0x314656c3 __CFRunLoopDoSource1 + 166
27 CoreFoundation 0x31457f7d __CFRunLoopRun + 520
28 CoreFoundation 0x31457c87 CFRunLoopRunSpecific + 230
29 CoreFoundation 0x31457b8f CFRunLoopRunInMode + 58
30 UIKit 0x338d5309 -[UIApplication _run] + 380
31 UIKit 0x338d2e93 UIApplicationMain + 670
32 myApp 0x000029bf main + 70
33 myApp 0x00002974 start + 40
)
terminate called after throwing an instance of 'NSException'
numberOfRows looks like:
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
NSLog(#"number of rows in section");
if (section == mySection) {
return [[articleArrays objectAtIndex:section] count];
} else {
return 0;
}
}
From what you describe here your process that performs the download, or more precisely an event callback should be the only place calling reload data. calling it after adding new data to the table dataSet.
returning a 0 in numberOfRowsInSection does not cause a crash but if you are trying to get a nested array when the count is 0, this will crash. Post your numberOfRowsInSection method for us to gawk at.
EDIT:
Sounds/Looks like background thread is mutating the array while its trying to do an object count.
user210504 is right in saying that synchronising the array is likely stop this.
Typically you would sync writes and therefore preventing numberOfRowsInSection from counting if your background thread is mutating it. eg:
-(void)downloadFinished{
NSMutableArray * array = [[NSArray alloc] init];//t
id * obj;//obj is your row data object.
#synchronized(ar)
{
[array addObject:obj];//ar is your dataSet
}
[array release];
}
One thing that you can do is to encapsulate accesses to the Mutable Array in #synchronized block. This way you will be sure that you are not accessing the datastructure half way through. And then I also agree with what Luke just mentioned.

My iPhone core data app runs perfectly the first time but crashes when run after that

my app is based around two classes: Jam and JamItem, each with a TableViewController to display / add items.
The model contains two entities for the two classes, and there is an optional one-to-one relationship between them. JamItem has a name field and a price field. Jam has a quantity field. There are corresponding NSManagedObject classes for the two entities.
Both lists are based on table list view controllers and were modelled on the Recipes example on the Apple site. The JamListTableViewController displays all JamItem instances that have been added to the list. When I click add, a new instance of JamItemListTableViewController is created and pushed onto the nav stack. This lists JamItem instances that have been created. When a JamItem is selected, the - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath method creates an instance of JamItem and passes it back via a delegate to JamListTableViewController. This then creates a new instance of Jam and adds the JamItem to it and then saves.
I can run the app perfectly when it is fresh on the simulator and run the first time with a clean database!
The JamItemListTableViewController always works and I can happily add and remove 'jam items' from the list. However, if I stop the app and re-run, then try to add a new JamItem to the jam list (JamListTableViewController), it crashes when JamListTableViewController calls the [jam.managedObjectContext save:&error] and I get the error below, which I think is where it is trying to sort by name.
The NSFetchedResultsController in JamItemListTableViewController is configured to order by name. The NSFetchedResultsController in JamItemListTableViewController is ordered by JamItem.name
I hope this makes sense as I have been pulling my hair out for weeks now trying to find the solution. I think I might have (or have not) released an object, which is causing the JamItem list to flag that it has been updated and start trying to re-sort its list.
This is the dump of the error:
2010-09-29 07:20:00.443 Jams[12451:207] Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. [<UINavigationItem 0x5b4dc30> valueForUndefinedKey:]: this class is not key value coding-compliant for the key name. with userInfo {
NSTargetObjectUserInfoKey = "<UINavigationItem: 0x5b4dc30>";
NSUnknownUserInfoKey = name;
}
2010-09-29 07:20:00.446 Jams[12451:207] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UINavigationItem 0x5b4dc30> valueForUndefinedKey:]: this class is not key value coding-compliant for the key name.'
*** Call stack at first throw:
(
0 CoreFoundation 0x02577919 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x026c55de objc_exception_throw + 47
2 CoreFoundation 0x02577851 -[NSException raise] + 17
3 Foundation 0x000d96b1 -[NSObject(NSKeyValueCoding) valueForUndefinedKey:] + 279
4 Foundation 0x00040868 _NSGetUsingKeyValueGetter + 147
5 Foundation 0x0003fd2e -[NSObject(NSKeyValueCoding) valueForKey:] + 278
6 Foundation 0x00043535 -[NSObject(NSKeyValueCoding) valueForKeyPath:] + 381
7 Foundation 0x000f7c4f -[NSSortDescriptor compareObject:toObject:] + 128
8 CoreData 0x0237cb5e +[NSFetchedResultsController(PrivateMethods) _insertIndexForObject:inArray:lowIdx:highIdx:sortDescriptors:] + 286
9 CoreData 0x0237d1b2 -[NSFetchedResultsController(PrivateMethods) _postprocessInsertedObjects:] + 402
10 CoreData 0x023831bc -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 1804
11 Foundation 0x00035c1d _nsnote_callback + 145
12 CoreFoundation 0x0254fcf9 __CFXNotificationPost_old + 745
13 CoreFoundation 0x024cf11a _CFXNotificationPostNotification + 186
14 Foundation 0x0002b7c2 -[NSNotificationCenter postNotificationName:object:userInfo:] + 134
15 CoreData 0x022bf519 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 89
16 CoreData 0x0232eb33 -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:] + 259
17 CoreData 0x022a1f78 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 1352
18 CoreData 0x022dba15 -[NSManagedObjectContext save:] + 149
19 JamsApp 0x000064b3 -[JamsListTableViewController insertJamItem:] + 168
20 JamsApp 0x00006405 -[JamsListTableViewController selectedJamItem:] + 43
21 JamsApp 0x00003f41 -[JamItemListTableViewController tableView:didSelectRowAtIndexPath:] + 143
22 UIKit 0x0033d718 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140
23 UIKit 0x00333ffe -[UITableView _userSelectRowAtIndexPath:] + 219
24 Foundation 0x0004acea __NSFireDelayedPerform + 441
25 CoreFoundation 0x02558d43 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
26 CoreFoundation 0x0255a384 __CFRunLoopDoTimer + 1364
27 CoreFoundation 0x024b6d09 __CFRunLoopRun + 1817
28 CoreFoundation 0x024b6280 CFRunLoopRunSpecific + 208
29 CoreFoundation 0x024b61a1 CFRunLoopRunInMode + 97
30 GraphicsServices 0x02ddc2c8 GSEventRunModal + 217
31 GraphicsServices 0x02ddc38d GSEventRun + 115
32 UIKit 0x002d9b58 UIApplicationMain + 1160
33 JamsApp 0x00001c0c main + 102
34 JamsApp 0x00001b9d start + 53
)
terminate called after throwing an instance of 'NSException'
I'd say check your nib to see if you have a connection to name, where name doesn't exist, but in suspect it would crash the first time too. Recheck everywhere you define name.
Ok, so I fixed it myself.
I am not completely sure what was going on, but it's seems to me that a field that was there originally and then removed, seemed to be in the core data somewhere?
Anyway, the fix for me was to remove all the core data files and managed object files and delete the instance of the app in the sim, and start again.
It took minutes to do and solved the problem - now jam can flow happily again!
I would have rather solved the problem, however time is in short supply and I already spent too many hours looking at it!

What is the possible reason of "[UIWindow length]: unrecognized selector" error

My iPhone app is a Tab Bar Application, which has 5 tabs. In each tab, there is a table view, embedded with navigation controller. When these table views appear, data will be loaded from database.
When I switch the tabs very fast by tapping the tab bar randomly, the app crashes sometimes.
The error is:
+[UIWindow length]: unrecognized selector sent to class 0x3e055bd4
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[UIWindow length]: unrecognized selector sent to class 0x3e055bd4'
terminate called after throwing an instance of 'NSException'
Does anyone have advices or hints about find out the reason of the problem?
P.S. I created another similar but simpler app, which cannot be crashed by this way.
More info about calling stack:
> *** Call stack at first throw:
(
0 CoreFoundation 0x31785fd3 __exceptionPreprocess + 114
1 libobjc.A.dylib 0x320118a5 objc_exception_throw + 24
2 CoreFoundation 0x31789af3 +[NSObject(NSObject) doesNotRecognizeSelector:] + 102
3 CoreFoundation 0x31788f15 ___forwarding___ + 508
4 CoreFoundation 0x3171b680 _CF_forwarding_prep_0 + 48
5 UIKit 0x3019a3ff -[UITableHeaderFooterView setText:] + 30
6 UIKit 0x3028239d -[UITableView(UITableViewInternal) _sectionHeaderView:withFrame:forSection:opaque:reuseViewIfPossible:] + 488
7 UIKit 0x30199e41 -[UITableView(UITableViewInternal) _sectionHeaderViewWithFrame:forSection:opaque:reuseViewIfPossible:] + 60
8 UIKit 0x3016bcb1 -[UITableView(_UITableViewPrivate) _updateVisibleHeadersAndFootersNow:] + 852
9 UIKit 0x3016b1a1 -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1408
10 UIKit 0x301693c1 -[UITableView layoutSubviews] + 140
11 UIKit 0x301276ab -[UIView(CALayerDelegate) _layoutSublayersOfLayer:] + 26
12 CoreFoundation 0x317117ff -[NSObject(NSObject) performSelector:withObject:] + 22
13 QuartzCore 0x321e2585 -[CALayer layoutSublayers] + 120
14 QuartzCore 0x321e233d CALayerLayoutIfNeeded + 184
15 QuartzCore 0x321e1e0f _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 210
16 QuartzCore 0x321e1b69 _ZN2CA11Transaction6commitEv + 192
17 QuartzCore 0x321e740d _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 52
18 CoreFoundation 0x3175ba49 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 16
19 CoreFoundation 0x3175d475 __CFRunLoopDoObservers + 412
20 CoreFoundation 0x3175e77b __CFRunLoopRun + 854
21 CoreFoundation 0x317078eb CFRunLoopRunSpecific + 230
22 CoreFoundation 0x317077f3 CFRunLoopRunInMode + 58
23 GraphicsServices 0x33ac26ef GSEventRunModal + 114
24 GraphicsServices 0x33ac279b GSEventRun + 62
25 UIKit 0x3011e2a7 -[UIApplication _run] + 402
26 UIKit 0x3011ce17 UIApplicationMain + 670
27 MyAPP 0x00002193 main + 70
28 MyAPP 0x00002114 start + 52
)
Most likely a dangling pointer to a former NSString now occupied by a UIWindow object. You'll have to find the lost object and probably retain it.
In XCode, select "Edit Active Executable..." under the Project menu. Select the "Arguments" tab and add an entry named "NSZombieEnabled" set to "YES" to the "Variables to be set in the environment" section.
NSZombieEnabled marks deleted objects as "Zombies" rather than reclaiming their space. When enabled, an exception is thrown any time a message is sent to a Zombie object. That should help you narrow down which object is not being retained properly.
Happy Zombie Hunting!
I can only guess that you try to call +[UIWindow length] somewhere in your code. And the method length does not exist in Apple API
Eventually, I found the problem.
I init a subview in viewWillApear: and use it in tableView:viewForHeaderInSection: and release the subview in viewDidDisappear:.
I changed the init/release into viewDidLoad: and viewDidUnload:. Then the problem is gone.
Thank both answerers and hope this answer will help others.