我在iPhone 4设备上的iOS7上遇到这个奇怪的问题,不确定是否会在较新的版本或设备中发生这种情况。我目前无法在目前使用iOS 11测试版的iPhone 6中复制此问题。
I have a Tableview with a NSFetchecResult as the table datasource.
The problem appears when I scroll the table this loop randomly happens.
this is the log:
2017-07-14 10:13:21.158 APP[28317:60b] cellForRowAtIndexPath <NSIndexPath: 0x18a58970> {length = 2, path = 3 - 0} 2017-07-14 10:13:21.223 APP[28317:60b] viewForHeaderInSection:4 2017-07-14 10:13:21.241 APP[28317:60b] cellForRowAtIndexPath:<NSIndexPath: 0x18f35450> {length = 2, path = 4 - 0} 2017-07-14 10:13:21.293 APP[28317:60b] scrollViewDidEndDragging -> notScrolling 2017-07-14 10:13:21.318 APP[28317:60b] scrollViewDidScroll -> isScrolling 2017-07-14 10:13:21.335 APP[28317:60b] viewForHeaderInSection:5 2017-07-14 10:13:21.354 APP[28317:60b] cellForRowAtIndexPath: <NSIndexPath: 0x18f34910> {length = 2, path = 5 - 0} 2017-07-14 10:13:21.404 APP[28317:60b] viewForHeaderInSection:6 2017-07-14 10:13:21.420 APP[28317:60b] cellForRowAtIndexPath:<NSIndexPath: 0x18f50cf0> {length = 2, path = 6 - 0} 2017-07-14 10:13:21.825 APP[28317:60b] scrollViewDidEndDecelerating -> >notScrolling 2017-07-14 10:13:21.855 APP[28317:60b] scrollViewWillBeginDragging -> isScrolling 2017-07-14 10:13:21.887 APP[28317:60b] cellForRowAtIndexPath:<NSIndexPath: 0x1763b350> {length = 2, path = 2 - 0} 2017-07-14 10:13:21.920 APP[28317:60b] viewForHeaderInSection:2 2017-07-14 10:13:21.958 APP[28317:60b] cellForRowAtIndexPath:<NSIndexPath: 0x18acb2b0> {length = 2, path = 1 - 0} 2017-07-14 10:13:21.992 APP[28317:60b] cellForRowAtIndexPath:<NSIndexPath: 0x18a2e640> {length = 2, path = 0 - 0} 2017-07-14 10:13:22.054 APP[28317:60b] viewForHeaderInSection:0 2017-07-14 10:13:22.070 APP[28317:60b] viewForHeaderInSection:1 2017-07-14 10:13:22.092 APP[28317:60b] numberOfSectionsInTableView 2017-07-14 10:13:22.100 APP[28317:60b] numberOfSectionsInTableView -> 7 2017-07-14 10:13:22.105 APP[28317:60b] numberOfRowsInSection:6 -> 1 2017-07-14 10:13:22.108 APP[28317:60b] numberOfRowsInSection:0 -> 1 2017-07-14 10:13:22.117 APP[28317:60b] numberOfRowsInSection:1 -> 1 2017-07-14 10:13:22.136 APP[28317:60b] numberOfRowsInSection:2 -> 1 2017-07-14 10:13:22.140 APP[28317:60b] numberOfRowsInSection:3 -> 1 2017-07-14 10:13:22.144 APP[28317:60b] numberOfRowsInSection:4 -> 1 2017-07-14 10:13:22.154 APP[28317:60b] numberOfRowsInSection:5 -> 1 2017-07-14 10:13:22.275 APP[28317:60b] numberOfSectionsInTableView 2017-07-14 10:13:22.284 APP[28317:60b] numberOfSectionsInTableView -> 7 2017-07-14 10:13:22.288 APP[28317:60b] numberOfRowsInSection:6 -> 1 2017-07-14 10:13:22.291 APP[28317:60b] numberOfRowsInSection:0 -> 1 2017-07-14 10:13:22.298 APP[28317:60b] numberOfRowsInSection:1 -> 1 2017-07-14 10:13:22.303 APP[28317:60b] numberOfRowsInSection:2 -> 1 2017-07-14 10:13:22.306 APP[28317:60b] numberOfRowsInSection:3 -> 1 2017-07-14 10:13:22.309 APP[28317:60b] numberOfRowsInSection:4 -> 1 2017-07-14 10:13:22.317 APP[28317:60b] numberOfRowsInSection:5 -> 1 2017-07-14 10:13:22.536 APP[28317:60b] numberOfSectionsInTableView 2017-07-14 10:13:22.540 APP[28317:60b] numberOfSectionsInTableView -> 7 2017-07-14 10:13:22.543 APP[28317:60b] numberOfRowsInSection:6 -> 1 2017-07-14 10:13:22.565 APP[28317:60b] numberOfRowsInSection:0 -> 1 2017-07-14 10:13:22.569 APP[28317:60b] numberOfRowsInSection:1 -> 1 2017-07-14 10:13:22.572 APP[28317:60b] numberOfRowsInSection:2 -> 1 2017-07-14 10:13:22.576 APP[28317:60b] numberOfRowsInSection:3 -> 1 2017-07-14 10:13:22.585 APP[28317:60b] numberOfRowsInSection:4 -> 1 2017-07-14 10:13:22.589 APP[28317:60b] numberOfRowsInSection:5 -> 1 2017-07-14 10:13:22.737 APP[28317:60b] numberOfSectionsInTableView 2017-07-14 10:13:22.741 APP[28317:60b] numberOfSectionsInTableView -> 7 2017-07-14 10:13:22.748 APP[28317:60b] numberOfRowsInSection:6 -> 1 2017-07-14 10:13:22.752 APP[28317:60b] numberOfRowsInSection:0 -> 1 2017-07-14 10:13:22.756 APP[28317:60b] numberOfRowsInSection:1 -> 1 2017-07-14 10:13:22.759 APP[28317:60b] numberOfRowsInSection:2 -> 1 2017-07-14 10:13:22.768 APP[28317:60b] numberOfRowsInSection:3 -> 1 2017-07-14 10:13:22.772 APP[28317:60b] numberOfRowsInSection:4 -> 1 2017-07-14 10:13:22.775 APP[28317:60b] numberOfRowsInSection:5 -> 1 2017-07-14 10:13:22.838 APP[28317:60b] numberOfSectionsInTableView
看起来tableview开始重新加载数据并在加载节标题的视图时进入循环。
这是我的tableview委托和数据源的代码: 在这里,我准备我的数据源
-(void) loadDBData
{
NSLog(@"loadDBData");
NSString *entityName = nil;
switch (_tableView.tag) {
case 1:
entityName = NSStringFromClass([Vehicle class]);
break;
case 2:
entityName = NSStringFromClass([Driver class]);
break;
default:
entityName = NSStringFromClass([Zone class]);
break;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName: entityName];
// Set the batch size to a suitable number.
// [fetchRequest setFetchBatchSize:5];
NSSortDescriptor *groupSort = [[NSSortDescriptor alloc] initWithKey:@"group.name" ascending:YES];
NSSortDescriptor *nameSort = nil;
switch (_tableView.tag) {
case 1:
nameSort = [[NSSortDescriptor alloc] initWithKey:@"vehicleDescription" ascending:YES];
break;
default:
nameSort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
break;
}
NSSortDescriptor *groupSortID = [[NSSortDescriptor alloc] initWithKey:@"group.id_group" ascending:YES];
fetchRequest.sortDescriptors = @[groupSort, groupSortID, nameSort];
self.fechedResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[DBController getDBController].managedObjectContext sectionNameKeyPath:@"group" cacheName:nil];
[self.fechedResultController setDelegate:self];
NSError *fetchingError = nil;
if([self.fechedResultController performFetch:&fetchingError])
{
NSLog(@"Successfully fetched.");
}
else
NSLog(@"Failed to fetch.");
}
这是我在coredata更改时管理的
#pragma mark - NSFetchResultsControllerDelegate
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
if(!_isScrolling)
{
NSLog(@"TableView Begins Update");
[self.tableView beginUpdates];
}
else
_tableViewNeedsToUpdate = YES;
}
-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
if(!_isScrolling)
{
switch(type) {
case NSFetchedResultsChangeInsert:
NSLog(@"didChangeObject -> NSFetchedResultsChangeInsert");
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
NSLog(@"didChangeObject -> NSFetchedResultsChangeDelete");
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
NSLog(@"didChangeObject -> NSFetchedResultsChangeUpdate");
[self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
NSLog(@"didChangeObject -> NSFetchedResultsChangeMove");
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
}
-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
if(!_isScrolling)
{
switch(type) {
case NSFetchedResultsChangeInsert:
NSLog(@"didChangeSection -> NSFetchedResultsChangeInsert");
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
NSLog(@"didChangeSection -> NSFetchedResultsChangeDelete");
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
default:
break;
}
}
}
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
if(!_isScrolling)
{
[self.tableView endUpdates];
NSLog(@"TableView Ends Update");
}
}
这就是我在做tableview的事情
#pragma mark - UITableView DataSource & Delegate
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(@"numberOfSectionsInTableView");
NSInteger nSections = 0;
id sectionInfo = [self.fechedResultController sections] ;
nSections = [sectionInfo count];
NSLog(@"numberOfSectionsInTableView -> %li", (long)nSections);
return nSections;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
NSLog(@"viewForHeaderInSection:%li",(long)section);
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fechedResultController sections] objectAtIndex:section];
if(sectionInfo)
{
NSString *sectionName = [[[[sectionInfo objects] firstObject] group]name];
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 28)];
[header setBackgroundColor:[UIColor lightGrayColor]];
UILabel *headerText = [[UILabel alloc] initWithFrame: CGRectMake(18, 4, tableView.frame.size.width - (18*2), 20)];
[headerText setTextColor:[UIColor blackColor]];
[headerText setFont:[UIFont fontWithName:@"Arial-BoldMT" size:20]];
[headerText setText: sectionName];
[header addSubview:headerText];
return header;
}
else
return nil;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// NSLog(@"numberOfRowsInSection:%i",section);
NSInteger nRows = 0;
id<NSFetchedResultsSectionInfo> sectionInfo = self.fechedResultController.sections[section];
nRows = sectionInfo.numberOfObjects;
NSLog(@"numberOfRowsInSection:%li -> %li",(long)section, (long)nRows);
return nRows;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"cellForRowAtIndexPath:%@",[indexPath description]);
// NSInteger section = indexPath.section;
// NSInteger row = indexPath.row;
FilterListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil)
cell = [[FilterListTableViewCell alloc] init];
[cell setMyDelegate:self];
id dataObject = [self.fechedResultController objectAtIndexPath:indexPath];
[cell setCellForObject: dataObject];
return cell;
}
- (void)configureCell:(FilterListTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"configureCell:atIndexPath%@",[indexPath description]);
id dataObject = [self.fechedResultController objectAtIndexPath:indexPath];
[cell setCellForObject: dataObject];
}
这是scroolDelegate的代码。我使用它来保证只有在没有滚动动画时才更新tabledata。 我在尝试识别并纠正问题时添加了这个,因为我认为滚动时表更新导致了问题。但仍然在循环。
#pragma mark - UIScroolView Delegate
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if(!_isScrolling)
{
_isScrolling = YES;
NSLog(@"scrollViewWillBeginDragging -> isScrolling");
}
}
- (void)scrollViewDidScroll:(UIScrollView *)sender
{
if(!_isScrolling)
{
_isScrolling = YES;
NSLog(@"scrollViewDidScroll -> isScrolling");
}
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if(_isScrolling)
{
_isScrolling = NO;
if (_tableViewNeedsToUpdate) {
[self.tableView reloadData];
_tableViewNeedsToUpdate = NO;
}
NSLog(@"scrollViewDidEndDragging -> notScrolling");
}
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
if(_isScrolling)
{
_isScrolling = NO;
if (_tableViewNeedsToUpdate) {
[self.tableView reloadData];
_tableViewNeedsToUpdate = NO;
}
NSLog(@"scrollViewDidEndDecelerating -> notScrolling");
}
}