bandw
bandw

Reputation: 889

Insert rows to UITableView crash

Im developing an app, need to load some data in background , then show the data using UITableView. Here are some codes,
loading data in background:

- (void)loadRelatedItems 
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    for (NSString *mediaType in allMediaTypes) 
    {
        [self performSelector:@selector(loadRelatedItems:) withObject:mediaType];
    }

    NSString *notificationName = [CommonFunction allRelatedItemsLoadedNotificationName];
    [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:self userInfo:nil];

    [pool release];
}

- (void)loadRelatedItems:(NSString *)mediaType 
{
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

   for (NSString *keyword in _keywords) 
   {
      NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@&mediaType=%@&keyword=%@", API, mediaType, keyword]];
      NSMutableArray *items = [CommonFunctions arrayFromURL:URL];

      if ([items count] == 0) continue;

      NSString *notificationName = [CommonFunction partialRelatedItemsLoadedNotificationName];
      NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:items, @"items", mediaType, @"mediaType", nil];
      [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:self userInfo:dic];   
   }

   [pool release];
}

showing the data in UITableView:

- (void)didFinishLoadPartialRelatedItems:(id)sender 
{
  NSDictionary *dic = [sender userInfo];
  NSString *mediaTypeString = [dic objectForKey:@"mediaType"];
  NSMutableArray *items = [dic objectForKey:@"items"];


  dispatch_async(dispatch_get_main_queue(), ^{

    if ([_relatedItems count] == 0) 
    {
        [_relatedItems setObject:items forKey:mediaTypeString];
        [_tableView reloadData];
    } 
    else 
    {
        NSMutableArray *mediaTypeItems = [_relatedItems objectForKey:mediaTypeString];

        if (mediaTypeItems) 
        { 
           // section exist
           NSInteger section =[[[_relatedItems allKeys] sortedArrayUsingSelector:@selector(mediaTypeCompare:)] indexOfObject:mediaTypeString];
           NSMutableArray *indexPaths = [NSMutableArray array];

           for (NSMutableDictionary *item in items) 
           {
               [mediaTypeItems addObject:item];
               NSInteger newRow = [mediaTypeItems indexOfObject:item];
               NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:newRow inSection:section];
               [indexPaths addObject:newIndexPath];
           }

           [_tableView beginUpdates];
           [_tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
           [_tableView endUpdates]; 
        }
        else 
        { 
            // new section

            [_relatedItems setObject:items forKey:mediaTypeString];
            NSInteger section =[[[_relatedItems allKeys] sortedArrayUsingSelector:@selector(mediaTypeCompare:)] indexOfObject:mediaTypeString];
            NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:section];
            [_tableView beginUpdates];
            [_tableView insertSections:indexSet withRowAnimation:UITableViewRowAnimationNone];
            [_tableView endUpdates];

        }

    }
});
}

#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if ([_relatedItems count] == 0) {
    return 1;
} else {

    return [_relatedItems count];
}
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{

NSArray *allTitles = [[_relatedItems allKeys] sortedArrayUsingSelector:@selector(mediaTypeCompare:)];
NSString *title = [allTitles objectAtIndex:section];
NSDictionary *allMediaTypeDisplayNames = [CommonFunction allMediaTypeDisplayNames];

return [allMediaTypeDisplayNames objectForKey:title];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([_relatedItems count] == 0) {
    return 0;
}
NSArray *allTitles = [[_relatedItems allKeys] sortedArrayUsingSelector:@selector(mediaTypeCompare:)];

NSString *title = [allTitles objectAtIndex:section];
NSInteger rowsCount = [[_relatedItems objectForKey:title] count];

return rowsCount;
}

I'm very confused that it works fine some times, but some times it crashed with message:

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableView.m:1030
*** 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 (0) must be equal to the number of sections contained in the table view before the update (2), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).

What's the problem? please help.

Upvotes: 2

Views: 845

Answers (2)

Manu
Manu

Reputation: 4750

Please make sure after updating, your number of sections should be equal to number of sections before the update.

As per your code :

the number of sections are defined as like this:

if ([_relatedItems count] == 0) {
    return 1;
} else {

    return [_relatedItems count];
}

and in this case you are creating new section right ?

else { // new section

            [_relatedItems setObject:items forKey:mediaTypeString];
            NSInteger section =[[[_relatedItems allKeys] sortedArrayUsingSelector:@selector(mediaTypeCompare:)] indexOfObject:mediaTypeString];
            NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:section];
            [_tableView beginUpdates];
            [_tableView insertSections:indexSet withRowAnimation:UITableViewRowAnimationNone];
            [_tableView endUpdates];

        }

If you are creating new section then your [_relatedItems count] is increasing. So, please make sure after the inserting also your count should be same.

Right ?

Try This :

if ([_relatedItems count] == 0) {
        return 1;
    } else {
        if([_relatedItems count]>previousCount)
            return [_relatedItems count];
        return previousCount;
    }

when ever you are making any updates to the [_relatedItems]; then change update your previousCount also.. this will be solved

Upvotes: 2

V-Xtreme
V-Xtreme

Reputation: 7333

I think your problem is with the number of rows method in the datasource just do one thing define int noOfRows in your .h file .assign your table view array count with the noOfRows. noOfRows=[yourtableArray count]; then return noOfRows from table views numberOfRowsInSection method. Add 1 to noOfRows if you insert row in the table. Make noOfRows-- when you delete row from the table You will not get this exception .Update your array as per your requirement.

Upvotes: 0

Related Questions