Assertion failure when trying to delete a row from UITableView - objective-c

I got an assertion failure when I try to delete a row from a UITableView using UITableViewCellEditingStyleDelete. Hope someone could tell me what is going wrong in my code.
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:1070
2013-01-30 14:19:21.450 MyApp[48313:c07] *** 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 (1) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
(0x28ee012 0x1d3fe7e 0x28ede78 0x19fef35 0xf51b8d 0xf5df95 0xf5dfc3 0xcfe9 0xf6c384 0x10a9b1b 0x1d53705 0xeb3920 0xeb38b8 0xf74671 0xf74bcf 0xf746a6 0x1144f95 0x1d53705 0xeb3920 0xeb38b8 0xf74671 0xf74bcf 0xf73d38 0xee333f 0xee3552 0xec13aa 0xeb2cf8 0x2d1adf9 0x2d1aad0 0x2863bf5 0x2863962 0x2894bb6 0x2893f44 0x2893e1b 0x2d197e3 0x2d19668 0xeb065c 0x24fd 0x2435)
libc++abi.dylib: terminate called throwing an exception
(lldb)
Here is my code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [records count];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete record from the sqlite database
NSNumber *recordDBID = [records objectAtIndex:indexPath.row];
Record *myRecord = [[Record alloc] initWithDBID:recordDBID database:UIAppDelegate.formManager.connection];
BOOL valueX = [myRecord deleteRecordInDb:recordDBID];
[myRecord release];
// Delete record from array
NSMutableArray *aNewArray = [[NSMutableArray alloc] initWithArray:records];
[aNewArray removeObjectAtIndex:indexPath.row];
records = aNewArray;
[aNewArray release];
// Delete the record from the table
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
[tableView reloadData];
}

I think there's a chance that you may be overcomplicating the removal of the table view row.
You do not need to call [tableView beginUpdates] and [tableView endUpdates] if you are only going to be removing a single row between those two calls, so you can lose them. Begin and end updates are only required if you are going to be carrying out multiple insert or delete actions at the same time.
Secondly, calling [tableView reloadData] at this point is overkill as the table view will automatically request the information it needs as part of the delete action using the assigned delegate/datasource. You can reduce the last part of the code to this:
// Delete the record from the table
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
It may be that the current row removal code (in combination with the wider code base) is confusing the system.
If the above does not help we'll need to see all code where the records array is being modified. In this event I'll update my answer.

In my case I have typos: it was indexPath instead newIndexPath in insertRowsAtIndexPaths
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)
{
switch type
{
case .Insert:
self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Bottom)
case .Delete:
self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .None)
case .Update:
self.tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
case .Move:
self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .None)
self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Bottom)
}
}

Related

How to perform the batch updates on table View in ios 10 and below in objective c

I have been using the core data for chat application and updating the chat table in delegate methods of NSfetchResultController controllerDidChangeContent
NSMutableArray<NSOperation *> *blockOpetations;
blockOpetations = [NSMutableArray new];
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.chatTable beginUpdates];
}
-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
switch (type) {
case NSFetchedResultsChangeInsert:{
[blockOpetations addObject:[NSBlockOperation blockOperationWithBlock: ^{
[self.chatTable insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationBottom];
}]];
}
break;
default:
break;
}
}
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
if (#available(iOS 11.0, *))
{
[self.chatTable performBatchUpdates:^
{
for(NSOperation *operation in blockOpetations)
{
[operation start];
}
} completion:^(BOOL finished)
{
NSInteger lastItem = [self.fetchedResultsController sections]
[0].numberOfObjects - 1;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:lastItem
inSection:0];
[self.chatTable scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}];
} else {
}
[self.chatTable endUpdates];
}
I am performing the batch updates on table view for iOS 11 and higher.
I want to perform the batch updates on table in iOS 10 and lower version , since batchupdate is not available below iOS 10.
I want to to know how to perform such thing in lower version.
I have taken the "blockOperation" an array of NSOperation , because if multiple message comes at the same time so table view updates the newly inserted rows serially without crash.
If I may have not taken the BlockOperation then some time the error comes
:
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 (20) must be equal to the number of rows contained in that section before the update (10), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).
The code written under method named "ControllerDidChangeContent", want to implement same task in iOS 10 and lower
Before iOS 11, this is done with
self.chatTable.beginUpdates()
// do stuff here
self.chatTable.endUpdates()

Realm notification on RLMArray not letting me update tables

I am currently trying to update my table view when a new chat message is sent. I set a notification block on my collection to notify the table view to begin updating but I keep getting an error saying there were 0 insertions:
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 (8)
must be equal to the number of rows contained in that section before the update (7),
plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted)
and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
Here is my notification code:
- (void)setUpRealmNotifications {
// Observe RLMResults Notifications
__weak typeof(self) weakSelf = self;
self.notificationToken = [[TERMessage objectsWhere:#"conversationID == %#", self.model.serverID] addNotificationBlock:^(RLMResults<TERMessage *> *results, RLMCollectionChange *change, NSError *error) {
if (error) {
NSLog(#"Failed to open Realm on background worker: %#", error);
return;
}
UITableView *tableView = weakSelf.tableView;
// Initial run of the query will pass nil for the change information
if (!change) {
[tableView reloadData];
return;
}
// Query results have changed, so apply them to the UITableView
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[change deletionsInSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:[change insertionsInSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadRowsAtIndexPaths:[change modificationsInSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
}];
}
From the looks of it, the change notification is coming down and updating the UITableView correctly, but it would seem that your UITableView data source isn't matching the same changes.
To ensure both the results of the change notification and the UITableView data source method in charge of managing the cells doesn't fall out of sync, I'd recommend keeping a single RLMResults instance around that both the change notification and table data source refer to.
#property (nonatomic, strong) RLMResults *items;
#property (nonatomic, strong) RLMNotificationToken *token;
// ---
self.items = [TERMessage objectsWhere:#"conversationID == %#", self.model.serverID];
self.token = [self.items addNotificationBlock:^...];
// ---
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TERMessage *message = self.items[indexPath.row];
UITableViewCell *cell = ...; //configure cell
return cell;
}

Core Data Table View Deleting Crash

I have a parent-child Core Data relationship set up in my iPhone app. I have a Manufacturer object and a Car object. It is a to-many relationship with the Manufacturer being the owner. The main view is a Table View containing the Manufacturers. The detail view is another Table View with the different types of cars. I have been using Tim Roadley's Core Data Tutorial as the base. This tutorial uses Stanford's Core Data Table View Library for the table views.
Adding Cars and Manufacturers gives me no problem, but when I go in and delete with multiple cars in the table view I get this error:
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:1037
2012-07-29 23:39:33.561 App [16368:c07] * 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 (0) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
If I delete the only car, it works fine until I try to add a new car, when I get this error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'manufacturer' between objects in different contexts (source = <Car: 0x6d96da0> (entity: Car; id: 0x6d8a3c0 <x-coredata:///Car/tC78E17EB-1D68-4998-8C4D-6D1199CE253F4> ; data: {
dateAdded = nil;
manufacturer = nil;
carName = new;
}) , destination = <Manufacturer: 0x6bb1f40> (entity: Manufacturer; id: 0x6d87340 <x-coredata://2E8DDF34-B01A-4203-A53E-73DBE6A2F976/Garden/p6> ; data: <fault>))'
Here is my editing method:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.tableView beginUpdates];
Plant *plantToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSLog(#"Deleting plant '%#'", plantToDelete.plantName);
[self.managedObjectContext deleteObject:plantToDelete];
[self.managedObjectContext save:nil];
//delete empty tableview row
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
NSLog(#"Before performFetch...");
[self performFetch];
NSLog(#"After performFetch...");
[self.tableView endUpdates];
}
}
The performFetch method is contained in the previously mentioned CoreDataTableViewController files. For your convenience, here it is:
(void)performFetch
{
_debug = YES;
if (self.fetchedResultsController) {
if (self.fetchedResultsController.fetchRequest.predicate) {
if (self.debug) NSLog(#"[%# %#] fetching %# with predicate: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName, self.fetchedResultsController.fetchRequest.predicate);
} else {
if (self.debug) NSLog(#"[%# %#] fetching all %# (i.e., no predicate)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName);
}
NSError *error;
[self.fetchedResultsController performFetch:&error];
if (error) NSLog(#"[%# %#] %# (%#)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]);
} else {
if (self.debug) NSLog(#"[%# %#] no NSFetchedResultsController (yet?)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
}
[self.tableView reloadData];
}
According to other questions, I am doing this correctly by using beginUpdates and endUpdates. This is a puzzling error. Thanks for your help.
I am not sure why you are performing the fetch again, if an object is removed from the context, the fetched results controller is aware of that change already. I think the main problem you have is calling perform fetch in the middle of processing updates to the table. If you comment that line out, does it still have the error?
Additionally, the following may or may not be another part of the the problem as this is where you are differing from my own code:
I have not seen the begin/end edits calls in tableView:CommitEditingStyle: before. My own process in that method generally deletes the object without any concern for the table row. The table rows are reconciled in the fetchedResultController delegate methods like so:
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
//the fetch controller is about to start sending change notifications so prepare the tableview
[self.tableView beginUpdates];
}
-(void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
// reconcile your rows here
switch(type) {
case NSFetchedResultsChangeInsert:
break;
case NSFetchedResultsChangeDelete:
// this one is you
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
break;
case NSFetchedResultsChangeUpdate:
break;
case NSFetchedResultsChangeMove:
break;
}
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
As long as the number of rows matches the number of fetched objects after all that, you should not have that error.
Try removing the lines
//delete empty tableview row
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
NSLog(#"Before performFetch...");
[self performFetch];
NSLog(#"After performFetch...");
I believe that CoreDataTableViewController will automatically handle removing the row from the table. You are essentially removing the row twice which is causing the error.
I was having the same error occur when I would open a tableViewController that was a subclass of Tim Roadley's CoreDataTableViewController. My specific app does not require the user to be able to add or delete rows, but it allows them to reorder the fetched results by name and by distance as well as search the data. I used Dean David's answer (the accepted answer above), but after every case statement I only added a break statement. So far that has worked for this app!

Delay when refreshing UITableView custom cell

I have a UITableView with a custom cell which i fill (with array infoservices) after parsing the xml data.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
ApplicationCell *cell = (ApplicationCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[self.cellNib instantiateWithOwner:self options:nil];
cell = tmpCell;
self.tmpCell = nil;
}
infoService *e = [self.infoservices objectAtIndex:indexPath.row];
cell.name = [e infoName];
NSString *infodetails = [e infoDetails];
if ( infodetails == nil ) {
cell.details = #"Loading...";
[self startInfoDownload:e forIndexPath:indexPath];
NSLog(#"Loading...");
} else {
cell.details = infodetails;
NSLog(#"Show info detail: %#", infodetails );
}
return cell;
}
- (void)infoDidFinishLoading:(NSIndexPath *)indexPath
{
infoDownloader *infoserv = [imageDownloadsInProgress objectForKey:indexPath];
if (infoserv != nil)
{
[infoservices replaceObjectAtIndex:[indexPath row] withObject:infoserv.appRecord];
NSIndexPath *a = [NSIndexPath indexPathForRow:indexPath.row inSection:0]; // I wanted to update this cell specifically
ApplicationCell *cell = (ApplicationCell *)[self.tableView cellForRowAtIndexPath:a];
cell.details = [[infoservices objectAtIndex:[indexPath row]] infoDetails];
NSLog(#"Updating=%#", [[infoservices objectAtIndex:[indexPath row]] infoDetails]);
}
}
For each cell i'm using NSURLConnection sendAsynchronousRequest to retrieve and parse xml data from object infoDownloader with
- (void)startDownload
for each individual cell.
After data has been successfully parsed delegate method from infoDownloader is called
- (void)infoDidFinishLoading:(NSIndexPath *)indexPath
The problem is that, while the
- (void)infoDidFinishLoading:(NSIndexPath *)indexPath
gets called after parsing each cell and i can see the
NSLog(#"Updating=%#", [[infoservices objectAtIndex:[indexPath row]] infoDetails]);
in the debugger with the correct details, the cell does not get refreshed immediately but after 6 or 7 seconds. Also cellForRowAtIndexPath does not get called from
- (void)infoDidFinishLoading:(NSIndexPath *)indexPath
for some reason because there is not debug output after the infoDidFinishLoading. Also i don't understand how the cell.details gets actually refreshed since cellForRowAtIndexPath isn't called again.
I've tried to setup this function using Apple's LazyTableImages loading example, which i have used successful, but i don't know what's going wrong.
You may need to call reloadRowsAtIndexPaths once the data has been loaded. What could be happening is that the cell data has been loaded but the cell drawing is not updated.
Also I believe your code can request the same data multiple times because if [e infoDetails] is nil a request is made, but the cell could be requested multiple times before the data is loaded so [self startInfoDownload:e forIndexPath:indexPath] would be called multiple times, downloading the same data. You should look into keeping track of which rows you have requested data for.
Check out this code for some ideas on how to solve this: https://github.com/kgn/Spectttator/blob/master/SpectttatorTest-iOS/RootViewController.m#L123
Any changes affecting UI must be performed on main thread.
Refreshing tableView, by changing cells details, realoading tabe view, realoding rows... are changes affecting UI.
In particular, you should perform your changes in the main thread using :
dispatch_async(dispatch_get_main_queue(), ^{
cell.details = [[infoservices objectAtIndex:[indexPath row]] infoDetails];
}
or prior to iOS 4 :
cell performSelectorOnMainThread:#selector(setDetails:) withObject:[[infoservices objectAtIndex:[indexPath row]] infoDetails];

Assertion failure in -[UITableView _endCellAnimationsWithContext:]

Hopefully this will be a quick fix. I have been trying to figure out the error that i keep getting. The error is listed below and the appdelagate is below that.
Any help is appreciated.
Thanks
2012-04-12 21:11:52.669 Chanda[75100:f803] --- Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:1037
2012-04-12 21:11:52.671 Chanda[75100:f803] --- 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 (2) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize databaseName,databasePath;
- (BOOL)application: (UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
self.databaseName = #"Customers.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [documentPaths objectAtIndex:0];
self.databasePath = [documentDir stringByAppendingPathComponent:self.databaseName];
[self createAndCheckDatabase];
return YES;
}
- (void)createAndCheckDatabase {
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:databasePath];
if (success) return;
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
#end
I don't see the reason for you to show us this part of code. Your error must be connected to this part in your code I assume
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
Probably you are making a mistake in one of these data source methods. Currently it's impossible to say what exactly is wrong but I assume it could be something like: You are telling the table view in the numberOfRowsInSection you would like to have n rows reserved and setup and in the cellForRowAtIndexPath you then only handle n - 1 rows for example.
Sorry that this answer can't be as precise as it should be. If you show us your implementation of your data source it would be much easier to tell what's going on.
Like Sun Tzu said: it's best to win without fighting. In my case whenever I see this kind of error message (ie discrepancy between rows added deleted etc).. I don't even debug anything.. I simply avoid making that extra call where I reload the rows etc.. that's 99% of the cases where this error happens.
This is a common scenario where this bug happens: I have a UINavigationController and it has a UITableView, when I click on a row it pushes a new UITableView and so on. This error always happens to me when I pop the last UITableview and go back to the UITableView before it, at this point I make an unnecessary call to the loadIt function which basically inserts the rows and relaods the UITableView.
The reason this happens is because I erroneously place my loadIt function in viewDidAppear:animated rather than viewDidLoad. viewDidAppear:animated is called every time the UITableView is displayed, viewDidLoad is only called once.
When removing rows, remember that it also checks sections when updating, in:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView
If you want to remove a row that is the last item in a section you need to remove the whole section instead (otherwise it might get section count wrong and throw this exception).
Don't forget to update your array which determines numberOfRowsInSection. It needs to be updated before you animate and remove
We check if number of rows in section is 1 because we will have to delete the entire section.
Do correct me if anyone can make this answer clearer.
[self.tableView beginUpdates];
if ([tableView numberOfRowsInSection:indexPath.section] == 1) {
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
} else {
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
[self.tableView endUpdates];
I put each section elements in separated arrays. Then put them into another array( arrayWithArray). My solution here for this problem:
[quarantineMessages removeObject : message];
[_tableView beginUpdates];
if([[arrayWithArray objectAtIndex: indPath.section] count] > 1)
{
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indPath] withRowAnimation:UITableViewRowAnimationBottom];
}
else
{
[_tableView deleteSections:[NSIndexSet indexSetWithIndex:indPath.section]
withRowAnimation:UITableViewRowAnimationFade];
}
[_tableView endUpdates];
I had the same error.
I was using the following lines
UINib *myCustomCellNib = [UINib nibWithNibName:#"CustomNib" bundle:nil];
[tableView registerNib:myCustomCellNib forCellReuseIdentifier:#"CustomNib"];
to register the nib in the viewDidLoad method, since I had a different nib that was also associated with the same class. Hence, the line
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"GBFBLoadingCell"];
was returning nil unless I registered the nib in the viewDidLoad.
My problem was that I forgot to set the identifier in the attributes inspector for my file "CustomNib.xib" and "CustomNib~iphone.xib". (Or more precisely, that I forgot to press enter after typing the identifier in the attribute inspector in XCode, so that the new name failed to save.)
Hope this helps.
If you're using an NSFetchedResultsController like me and updating data in a background thread, don't forget to begin and end updates in the delegate:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
I Had the same error , which when trying with [tableView reloadData] was working fine .
The error was actually in the line
[TabView insertRowsAtIndexPaths:indexPathsArray withRowAnimation:UITableViewRowAnimationRight];
When i tried to check the indexPath values , they weren't correct as required .
I fixed it by changing values in indexPathsArray .
Hope this helps .
Its could be one of UITableViewDataSource protocol methods
For
- tableView:numberOfRowsInSection:
it should return an integer equal to the sum or result of
-insertRowsAtIndexPaths:withRowAnimation: and/or -deleteRowsAtIndexPaths:withRowAnimation:
For
- numberOfSectionsInTableView:
it should return an integer equal to the sum or result of
-insertRowsAtIndexPaths:withRowAnimation: and/or
-deleteSections:withRowAnimation:
I had the same problem with a Core Data base. If your using many FRC, you just need to reload the tableview inside each condition in numberOfSectionsInTableView.
I just had this happen to me while using Swift and a FRC backed data store to manage information. Adding a simple check to the delete operation to evaluate the current indexPath.section allowed me to avoid an extraneous call. I think I understand why this problem occurs... Basically I load a message into the top row whenever my dataset is empty. This creates an off by one issue as there is a faux row.
My Solution
... delete my entity, save the datastore and call reloadData on tableView
//next I add this simple check to avoid calling deleteRows when the system (wrongly) determines that there is no section.
if indexPath.section > 0 {
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
Simply check that you call [yourTableView reloadData]; after modify array of values.