endUpdates之后的UITableView部分页脚视图位置

时间:2014-10-07 16:12:15

标签: ios objective-c uitableview ios8

在ios8上,我正在使用核心数据表视图控制器,删除行后,我的部分页脚视图突然一直向下到UITableView的底部。当我滚动表格视图时,页脚视图会返回到它的位置。如何解决这个问题以及为什么会发生这种情况?

以下是以防万一的代码。

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{       
    if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
    {
        switch(type)
        {
            case NSFetchedResultsChangeInsert:
                [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;

            case NSFetchedResultsChangeDelete:
                [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
                break;

            case NSFetchedResultsChangeUpdate:
                [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;

            case NSFetchedResultsChangeMove:
                [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;
        }
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    if (self.beganUpdates)
    {
       [self.tableView endUpdates];
    }
}

5 个答案:

答案 0 :(得分:11)

这是iOS 8动画更改。您必须将tableview样式更改为“分组”,以防止部分页脚移动到uitableview的引导程序

答案 1 :(得分:3)

我刚遇到同样的问题。当我使用insertRowsAtIndexPaths时...页脚会移到底部。还注意到如果你在表视图上调用reloadData,它将解决问题所以我这样做了:

[CATransaction begin];
[CATransaction setCompletionBlock: ^{
    // Code to be executed upon completion
    [tableView reloadData];
}];

[tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationLeft];
[CATransaction commit]; 

它所做的只是在插入动画完成时重新加载表格... 这不是一个真正的解决方案,更像是避免问题,但它隐藏了问题,直到有人解释为什么会发生这种问题以及如何解决它....

答案 2 :(得分:1)

我遇到了同样的问题,并花了很多精力试图解决它。现在,终于!

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {

        NATask *task = sections[indexPath.section][indexPath.row];
        [sections[indexPath.section] removeObjectAtIndex:indexPath.row];
        [appDelegate.managedObjectContext deleteObject:task];

        [CATransaction begin];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

        UIView *footerView = [tableView footerViewForSection:indexPath.section];
        CABasicAnimation *animation = [[footerView.layer animationForKey:@"position"] mutableCopy];
        CGPoint fromValue = [(NSValue *)animation.fromValue CGPointValue];
        animation.toValue = [NSValue valueWithCGPoint:CGPointMake(0, fromValue.y - 44)];
        [footerView.layer removeAnimationForKey:@"position"];
        [footerView.layer addAnimation:animation forKey:@"position"];
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, .4 * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [tableView reloadData];
        });

        [CATransaction commit];
    }
}

当然,这不是最理想的解决方案,但它确实有效!我差不多两个星期都在解决这个问题,我希望,至少对某人有用。

答案 3 :(得分:0)

我遇到了同样的问题。到目前为止,答案都没有给我我正在寻找的东西。将表格视图设置为'分组'没有我想要的行为,其他解决方案仍然导致页脚暂时位于表视图的底部,直到调用reloadData,它们突然将其重新捕捉到正确的位置。

以下是我的解决方案,可以顺利地将其动画到应该的位置。

NSIndexPath* iPath = [NSIndexPath indexPathForRow:_lineItemArray.count-1 inSection:0];

// Calculate the Y position of the bottom of the footer within the table view frame.
CGFloat footerBaseY = (_footer.y + _footer.height) - _sTableView.contentOffset.y;
// Calculate the Y position of the bottom taking into account the bottom content inset.
CGFloat tableViewContentBottomY = _sTableView.height - _sTableView.contentInset.bottom;

if (footerBaseY < tableViewContentBottomY) {
    [_sTableView insertRowsAtIndexPaths:@[iPath] withRowAnimation:UITableViewRowAnimationBottom];
    [UIView animateWithDuration:0.3
                     animations:^{
                         CGFloat y = _lineItemArray.count * [_sTableView rectForRowAtIndexPath:iPath].size.height;
                         CGFloat newBaseY = (y + _footer.height) - _sTableView.contentOffset.y;

                         if (newBaseY < tableViewContentBottomY) {
                             _footer.y = y;
                         } else {
                             // The footer is within a cell's height away from the bottom.  Subtract the diff from the new y.
                             _footer.y = y - (newBaseY - tableViewContentBottomY);
                         }
                     } completion:^(BOOL finished) {
                         // This ensures that the bottom row animates up if the footer was within a cell's height away from the bottom.
                         [_sTableView scrollToRowAtIndexPath:iPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
                     }];
} else {
    // The footer was already at the bottom of the vew so I'm animating the added row up.
    [_sTableView insertRowsAtIndexPaths:@[iPath] withRowAnimation:UITableViewRowAnimationBottom];
    [_sTableView scrollToRowAtIndexPath:iPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

答案 4 :(得分:0)

我仍然需要部分页眉和页脚视图是粘性的。因此,我没有将tableview样式更改为Grouped,而是在删除行后简单地执行了reloadSection ......