iOS Application Terminates After Exception Thrown in UITableViewDataSource Method - iphone

Having meticulously followed the examples and instructions in the Table View Programming Guide for iOS about the proper order in which UITableView delegate and data source methods are called, I thought I had a good idea of how to implement the “handshake” shown in Figure 7-1 and the list that follows, but apparently not.
Here's the code I'm using…
- (void) tableView: (UITableView *) tableView commitEditingStyle: (UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath {
NSLog(#"Removing %# row %d.", [dataModel objectAtIndex: indexPath.row], indexPath.row);
[tableView deleteRowsAtIndexPaths: [NSArray arrayWithObjects: indexPath, nil] withRowAnimation: UITableViewRowAnimationFade];
[dataModel removeObjectAtIndex: indexPath.row];
}
tableView is the UITableView
dataModel is an NSArray instance that holds the objects represented by the UITableViewCells from the tableView.
…and the error I'm getting…
2010-08-27 21:53:17.971 SportWatch[1299:307] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-1262.58/UITableView.m:920
2010-08-27 21:53:17.992 SportWatch[1299:307] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (4), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).'
*** Call stack at first throw:
(
0 CoreFoundation 0x35411ed3 __exceptionPreprocess + 114
1 libobjc.A.dylib 0x311f0811 objc_exception_throw + 24
2 CoreFoundation 0x35411d15 +[NSException raise:format:arguments:] + 68
3 Foundation 0x332b932f -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 62
4 UIKit 0x338dcda1 -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] + 4524
5 UIKit 0x338d586d -[UITableView _updateRowsAtIndexPaths:updateAction:withRowAnimation:] + 204
6 UIKit 0x338d5775 -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] + 20
7 SportWatch 0x000060e7 -[MainViewController tableView:commitEditingStyle:forRowAtIndexPath:] + 670
8 UIKit 0x338d3c3f -[UITableView(UITableViewInternal) animateDeletionOfRowWithCell:] + 58
9 UIKit 0x33984071 -[UITableViewCell(UITableViewCellInternal) deleteConfirmationControlWasClicked:] + 28
10 CoreFoundation 0x353b9719 -[NSObject(NSObject) performSelector:withObject:withObject:] + 24
11 UIKit 0x33831d59 -[UIApplication sendAction:to:from:forEvent:] + 84
12 UIKit 0x33831cf9 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 32
13 UIKit 0x33831ccb -[UIControl sendAction:to:forEvent:] + 38
14 UIKit 0x33831a1d -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 356
15 UIKit 0x3383206b -[UIControl touchesEnded:withEvent:] + 342
16 UIKit 0x338309f5 -[UIWindow _sendTouchesForEvent:] + 368
17 UIKit 0x3383036f -[UIWindow sendEvent:] + 262
18 UIKit 0x3382ae13 -[UIApplication sendEvent:] + 298
19 UIKit 0x3382a74b _UIApplicationHandleEvent + 5110
20 GraphicsServices 0x3171a04b PurpleEventCallback + 666
21 CoreFoundation 0x353a6ce3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
22 CoreFoundation 0x353a6ca7 __CFRunLoopDoSource1 + 166
23 CoreFoundation 0x3539956d __CFRunLoopRun + 520
24 CoreFoundation 0x35399277 CFRunLoopRunSpecific + 230
25 CoreFoundation 0x3539917f CFRunLoopRunInMode + 58
26 GraphicsServices 0x317195f3 GSEventRunModal + 114
27 GraphicsServices 0x3171969f GSEventRun + 62
28 UIKit 0x337d148b -[UIApplication _run] + 402
29 UIKit 0x337cf69f UIApplicationMain + 670
30 SportWatch 0x00002b23 main + 70
31 SportWatch 0x00002ad8 start + 40
)
terminate called after throwing an instance of 'NSException'
Program received signal: “SIGABRT”.
kill
Current language: auto; currently objective-c
quit

remove the object from the data set before deleting the row.

Related

unrecognized selector sent to instance when no related entities found in Core Data

I have a Core Data problem - I have two entity's with the second being a one to many relation ship to the first. When trying to load a detailed view controller on the first with the first one's information and a UITableView fo the details of the 2nd, I am hoping this tableView code would allow me to show a blank table if now records are found. Instead I get a crash as indicated above. I have tried to cover the "Event" (the related NSSet) into an array, but I am not sure how to debug this error. Thanks for any pointers!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath)
let eventsOnArray = selectedRecipient?.events.allObjects
let event = eventsOnArray![indexPath.row] as! Event
if selectedRecipient?.events.count != nil {
cell.textLabel?.text = event.event
}
return cell
}
Adding detailed Stack Trace -
2018-03-03 10:27:29.419115-0500 Card Tracker[5162:453078] -[Recipient events]: unrecognized selector sent to instance 0x60000009cbb0
2018-03-03 10:27:29.427781-0500 Card Tracker[5162:453078] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Recipient events]: unrecognized selector sent to instance 0x60000009cbb0'
*** First throw call stack:
(
0 CoreFoundation 0x0000000107fd212b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x0000000103d79f41 objc_exception_throw + 48
2 CoreFoundation 0x0000000108053024 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x0000000107f54f78 ___forwarding___ + 1432
4 CoreFoundation 0x0000000107f54958 _CF_forwarding_prep_0 + 120
5 Card Tracker 0x0000000103434fca _T012Card_Tracker010ViewEventsC10ControllerC05tableC0SiSo07UITableC0C_Si21numberOfRowsInSectiontF + 410
6 Card Tracker 0x00000001034352e4 _T012Card_Tracker010ViewEventsC10ControllerC05tableC0SiSo07UITableC0C_Si21numberOfRowsInSectiontFTo + 68
7 UIKit 0x0000000104cd1b4c -[UITableView _numberOfRowsInSection:] + 62
8 UIKit 0x0000000104f840e1 -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 2389
9 UIKit 0x0000000104f8a5ab -[UITableViewRowData rectForFooterInSection:heightCanBeGuessed:] + 487
10 UIKit 0x0000000104f8a711 -[UITableViewRowData heightForTable] + 61
11 UIKit 0x0000000104c7fa65 -[UITableView _updateContentSize] + 372
12 UIKit 0x0000000104cb067d -[UITableView _rebuildGeometry] + 66
13 UIKit 0x0000000104cae03c -[UITableView didMoveToWindow] + 145
14 UIKit 0x0000000104c2b147 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1748
15 UIKit 0x0000000104c44a81 -[UIScrollView _didMoveFromWindow:toWindow:] + 84
16 UIKit 0x0000000104c2ad84 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 785
17 UIKit 0x0000000104c1d1e1 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 151
18 UIKit 0x0000000104c1d0c8 -[UIView(Hierarchy) _postMovedFromSuperview:] + 828
19 UIKit 0x0000000104c2dcbd -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1973
20 UIKit 0x0000000104b504e7 -[_UIParallaxDimmingView didMoveToWindow] + 179
21 UIKit 0x0000000104c2b147 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1748
22 UIKit 0x0000000104c2ad84 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 785
23 UIKit 0x0000000104c1d1e1 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 151
24 UIKit 0x0000000104c1d0c8 -[UIView(Hierarchy) _postMovedFromSuperview:] + 828
25 UIKit 0x0000000104c2dcbd -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1973
26 UIKit 0x0000000104b4b259 __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke_2 + 2305
27 UIKit 0x0000000104c25c60 +[UIView(Animation) performWithoutAnimation:] + 90
28 UIKit 0x0000000104b4a903 __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke + 260
29 UIKit 0x0000000104c2c271 +[UIView(Internal) _performBlockDelayingTriggeringResponderEvents:] + 188
30 UIKit 0x0000000104b4a21b -[_UINavigationParallaxTransition animateTransition:] + 1270
31 UIKit 0x0000000104d3e3ee -[UINavigationController _startCustomTransition:] + 3678
32 UIKit 0x0000000104d543b4 -[UINavigationController _startDeferredTransitionIfNeeded:] + 686
33 UIKit 0x0000000104d556d3 -[UINavigationController __viewWillLayoutSubviews] + 150
34 UIKit 0x0000000104fb04e2 -[UILayoutContainerView layoutSubviews] + 231
35 UIKit 0x0000000121187008 -[UILayoutContainerViewAccessibility layoutSubviews] + 42
36 UIKit 0x0000000104c34a6d -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1439
37 QuartzCore 0x000000010b5d361c -[CALayer layoutSublayers] + 159
38 QuartzCore 0x000000010b5d77ad _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 401
39 QuartzCore 0x000000010b55e86c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 364
40 QuartzCore 0x000000010b58b946 _ZN2CA11Transaction6commitEv + 500
41 UIKit 0x0000000104b8d167 _afterCACommitHandler + 272
42 CoreFoundation 0x0000000107f74c07 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
43 CoreFoundation 0x0000000107f74b5e __CFRunLoopDoObservers + 430
44 CoreFoundation 0x0000000107f59124 __CFRunLoopRun + 1572
45 CoreFoundation 0x0000000107f58889 CFRunLoopRunSpecific + 409
46 GraphicsServices 0x000000010a77b9c6 GSEventRunModal + 62
47 UIKit 0x0000000104b635d6 UIApplicationMain + 159
48 Card Tracker 0x0000000103417ea7 main + 55
49 libdyld.dylib 0x0000000109170d81 start + 1
50 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Two problems uncovered. one in the data model the secondary entity is called card not events. And two as pointed out by #vadian above should do the load in the viewDidLoad. Thanks

ios core data cannot find NSManagedObjectModel for entity name 'Cartdetail' with this code

Hi i'm creating an app that needs to save data in my label content to my core data model which is named as cart.xcdatamodeld and my entity named as Cartdetail.When i press a save button in my app i'm getting following error...
- (void)viewDidLoad {
if (managedObjectContext == nil) {
managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate]managedObjectContext];
}
}
- (IBAction)SaveTest:(id)sender {
ViewController2 *second = (ViewController2 *)[NSEntityDescription insertNewObjectForEntityForName:#"Cartdetail" inManagedObjectContext:managedObjectContext];
}
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'Cartdetail''
*** Call stack at first throw:
(
0 CoreFoundation 0x010265a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x01444313 objc_exception_throw + 44
2 CoreData 0x00036ebb +[NSEntityDescription entityForName:inManagedObjectContext:] + 187
3 CoreData 0x0006e9eb +[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:] + 59
4 tablevc 0x00009c97 -[Description alertView:clickedButtonAtIndex:] + 519
5 UIKit 0x00621c5f -[UIAlertView(Private) _buttonClicked:] + 296
6 UIKit 0x002784fd -[UIApplication sendAction:to:from:forEvent:] + 119
7 UIKit 0x00308799 -[UIControl sendAction:to:forEvent:] + 67
8 UIKit 0x0030ac2b -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
9 UIKit 0x003097d8 -[UIControl touchesEnded:withEvent:] + 458
10 UIKit 0x0029cded -[UIWindow _sendTouchesForEvent:] + 567
11 UIKit 0x0027dc37 -[UIApplication sendEvent:] + 447
12 UIKit 0x00282f2e _UIApplicationHandleEvent + 7576
13 GraphicsServices 0x01c34992 PurpleEventCallback + 1550
14 CoreFoundation 0x01007944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
15 CoreFoundation 0x00f67cf7 __CFRunLoopDoSource1 + 215
16 CoreFoundation 0x00f64f83 __CFRunLoopRun + 979
17 CoreFoundation 0x00f64840 CFRunLoopRunSpecific + 208
18 CoreFoundation 0x00f64761 CFRunLoopRunInMode + 97
19 GraphicsServices 0x01c331c4 GSEventRunModal + 217
20 GraphicsServices 0x01c33289 GSEventRun + 115
21 UIKit 0x00286c93 UIApplicationMain + 1160
22 tablevc 0x00001d4a main + 170
23 tablevc 0x00001c95 start + 53
)
terminate called throwing an exception
I'm new to iOS..Please help me..Thanks..
You probably haven't set up your managed object context in AppDelegate!
Take a look at the AppDelegate implementation of the iPhoneCoreDataRecipes example provided by apple:
iPhoneCoreDataRecipes example

"Drink Mixer" Example Head First iPhone & iPad Development

i'm kinda new to Objective-C so i have been learning with the Head First iPhone & iPad Development book. In this book, at the Chapter 4-5 you suppose to design an app for a bartender, that basically is a table view of a list of drinks with the details list (it suppose to have the ingredients and directions for the drink selected). The data comes from two property lists, one has a list of strings with the names of the drinks, and the other is a Dictionary that has the name, directions and ingredients of the drinks.
I have followed the tutorial and the app crashes, re-checked it and still crashes. I'm using an Xcode Version of 4.0.1 and MAC OS X 10.6.8.
Here is the exception, i hope that you guys can check out what happens at this simple application.
2012-07-19 21:43:39.757 DrinkMixer[846:207] -[NSCFString objectForKey:]: unrecognized selector sent to instance 0x4b31220
2012-07-19 21:43:39.761 DrinkMixer[846:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString objectForKey:]: unrecognized selector sent to instance 0x4b31220'
*** Call stack at first throw:
(
0 CoreFoundation 0x00dc25a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x00f16313 objc_exception_throw + 44
2 CoreFoundation 0x00dc40bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x00d33966 ___forwarding___ + 966
4 CoreFoundation 0x00d33522 _CF_forwarding_prep_0 + 50
5 DrinkMixer 0x00002495 -[RootViewController tableView:cellForRowAtIndexPath:] + 325
6 UIKit 0x00089b98 -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] + 634
7 UIKit 0x0007f4cc -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] + 75
8 UIKit 0x000948cc -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1561
9 UIKit 0x0008c90c -[UITableView layoutSubviews] + 242
10 QuartzCore 0x016aca5a -[CALayer layoutSublayers] + 181
11 QuartzCore 0x016aeddc CALayerLayoutIfNeeded + 220
12 QuartzCore 0x016540b4 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 310
13 QuartzCore 0x01655294 _ZN2CA11Transaction6commitEv + 292
14 UIKit 0x000169c9 -[UIApplication _reportAppLaunchFinished] + 39
15 UIKit 0x00016e83 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 690
16 UIKit 0x00021617 -[UIApplication handleEvent:withNewEvent:] + 1533
17 UIKit 0x00019abf -[UIApplication sendEvent:] + 71
18 UIKit 0x0001ef2e _UIApplicationHandleEvent + 7576
19 GraphicsServices 0x00ffb992 PurpleEventCallback + 1550
20 CoreFoundation 0x00da3944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
21 CoreFoundation 0x00d03cf7 __CFRunLoopDoSource1 + 215
22 CoreFoundation 0x00d00f83 __CFRunLoopRun + 979
23 CoreFoundation 0x00d00840 CFRunLoopRunSpecific + 208
24 CoreFoundation 0x00d00761 CFRunLoopRunInMode + 97
25 UIKit 0x000167d2 -[UIApplication _run] + 623
26 UIKit 0x00022c93 UIApplicationMain + 1160
27 DrinkMixer 0x00001c89 main + 121
28 DrinkMixer 0x00001c05 start + 53
)
terminate called after throwing an instance of 'NSException'
sharedlibrary apply-load-rules all
(gdb)
And here is exactly when the app crashes, at the objectForKey:#"name"
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [[self.drinks objectAtIndex:indexPath.row] objectForKey:#"name"];
return cell;
}
the clue in the first line of the error is that you have initialized the contents of self.drinks at the index that corresponds to indexPath.row to be an NSString. when that objectAtIndex: is retrieved, it is then passed the message objectForKey: as though it is an NSArray.
look at the code where you've initialized self.drinks and make certain you've made it an appropriate array containing appropriate contents. in your case, it would be an array of NSDictionary* for objectForKey: to work).
Debug your code and check drinks is an array of NSDictonary.

Error when testing application on iPhone, but no error in simulator

I get the below error when I test my application on my iPhone, yet the error doesnt occur in the Simulator. Its when I load up my rootViewController which is a UITableView. I am relatively new to iOS programming, and I was just wondering if anybody could shed any light on it!
Regards,
Michael.
Use this code to go to my RootView.
- (IBAction)goToRootView {
RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:rootViewController animated:YES];
[rootViewController release];
}
2011-09-12 14:39:55.951 LeagueProject[773:707] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array'
*** Call stack at first throw:
(
0 CoreFoundation 0x3684b64f __exceptionPreprocess + 114
1 libobjc.A.dylib 0x33aa4c5d objc_exception_throw + 24
2 CoreFoundation 0x367b6069 -[__NSArrayM objectAtIndex:] + 184
3 LeagueProject 0x0000302f -[RootViewController tableView:numberOfRowsInSection:] + 58
4 UIKit 0x356827c7 -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 1338
5 UIKit 0x356836bb -[UITableViewRowData rectForFooterInSection:] + 66
6 UIKit 0x356835f5 -[UITableViewRowData heightForTable] + 40
7 UIKit 0x35683453 -[UITableView(_UITableViewPrivate) _updateContentSize] + 206
8 UIKit 0x3567ebc9 -[UITableView _rectChangedWithNewSize:oldSize:] + 384
9 UIKit 0x3567d833 -[UITableView setFrame:] + 158
10 UIKit 0x35684e0f -[UIView(Geometry) resizeWithOldSuperviewSize:] + 274
11 UIKit 0x356510bd -[UIView(Geometry) resizeSubviewsWithOldSize:] + 120
12 UIKit 0x356364e9 -[UIView(Geometry) setFrame:] + 336
13 UIKit 0x35688193 -[UIViewControllerWrapperView setFrame:] + 62
14 UIKit 0x35676079 -[UINavigationController _startTransition:fromViewController:toViewController:] + 960
15 UIKit 0x35675c43 -[UINavigationController _startDeferredTransitionIfNeeded] + 182
16 UIKit 0x35667d5d -[UINavigationController pushViewController:transition:forceImmediate:] + 640
17 UIKit 0x35667ad3 -[UINavigationController pushViewController:animated:] + 34
18 LeagueProject 0x0000917d -[splashView goToRootView] + 116
19 CoreFoundation 0x367bb571 -[NSObject(NSObject) performSelector:withObject:withObject:] + 24
20 UIKit 0x3564dec9 -[UIApplication sendAction:to:from:forEvent:] + 84
21 UIKit 0x3564de69 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 32
22 UIKit 0x3564de3b -[UIControl sendAction:to:forEvent:] + 38
23 UIKit 0x3564db8d -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 356
24 UIKit 0x3564e423 -[UIControl touchesEnded:withEvent:] + 342
25 UIKit 0x3564cbf5 -[UIWindow _sendTouchesForEvent:] + 368
26 UIKit 0x3564c56f -[UIWindow sendEvent:] + 262
27 UIKit 0x35635313 -[UIApplication sendEvent:] + 298
28 UIKit 0x35634c53 _UIApplicationHandleEvent + 5090
29 GraphicsServices 0x35f6fe77 PurpleEventCallback + 666
30 CoreFoundation 0x36822a97 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
31 CoreFoundation 0x3682483f __CFRunLoopDoSource1 + 166
32 CoreFoundation 0x3682560d __CFRunLoopRun + 520
33 CoreFoundation 0x367b5ec3 CFRunLoopRunSpecific + 230
34 CoreFoundation 0x367b5dcb CFRunLoopRunInMode + 58
35 GraphicsServices 0x35f6f41f GSEventRunModal + 114
36 GraphicsServices 0x35f6f4cb GSEventRun + 62
37 UIKit 0x3565fd69 -[UIApplication _run] + 404
38 UIKit 0x3565d807 UIApplicationMain + 670
39 LeagueProject 0x000025a7 main + 82
40 LeagueProject 0x00002550 start + 40
)
terminate called after throwing an instance of 'NSException'
Your error is an index 0 beyond bounds for empty array error. Put breakpoints on the lines where you access arrays. When you find out which array is causing the problem, either the solution will be trivial, or you can add a bit more to your question and ask for further help.
It looks like the problem is in your implementation of [RootViewController tableView:numberOfRowsInSection:]. You are trying to access a member of a NSMutableArray that is empty - hence the error 'index 0 beyond bounds for empty array'.

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.