UITableView单元格插入行故障

时间:2019-05-02 05:30:46

标签: ios uitableview

我有一个带有自定义单元格的表视图(所有单元格都使用自动布局在子类中配置)。

单元格加载正常,显示正常,一切正常。

问题是当我在底部插入更多行时。表格视图代表帖子的供稿,因此当用户滚动到底部时,在到达最后一个单元格之前,我加载了新帖子,然后将它们插入表格中。

当我这样做时,我得到了这种奇怪的毛刺效果,即单元格随机下降(位于前一个单元格之后)到位,表格视图向上滚动,有点混乱。

底部代码

我上传了一个我正在滚动的剪辑。当您看到活动指示器时, 我停止滚动。运动的其余部分来自故障行为。

enter image description here


  • 出现毛刺的原因是因为使用自动布局绘制单元格吗?

我不希望,但是idk ..我不确定该怎么做。如果有人有任何想法,请告诉我。

仅供参考:

我有这个(当然,因为所有单元格都使用自动布局)

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

我尝试将估计高度设置为预期单元格高度的“平均值”,约为65。没有区别。

更新

以下是一些代码:

HomeViewController.m -> viewDidLoad

...
self.tableView = [KATableView.alloc initWithFrame:CGRectZero style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.refreshDelegate = self;

self.tableView.estimatedRowHeight = 75;
self.tableView.rowHeight = UITableViewAutomaticDimension;

[self.view addSubview:self.tableView];

// Constrains to all 4 sides of self.view
[SSLayerEffects constrainView:self.tableView toAllSidesOfView:self.view];

我的表格视图数据源

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (!self.dataManager.didFinishFetchingData) return 4;
    if (self.contentObjects.count == 0) return 1;
    if (self.dataManager.moreToLoad) return self.contentObjects.count + 1;
    return self.contentObjects.count + 1;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    MYObject *object = self.contentObjects[indexPath.row];
    SomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:object.documentID];

    if (!cell) {
        cell = [SomeTableViewCell.alloc initWithStyle:UITableViewCellStyleDefault reuseIdentifier:object.documentID];
            cell.delegate = self;
    } else [cell startListeningForChanges];


    return cell;

}

这是我加载更多数据并将其添加到表格视图中的方式。

- (void)getHomeFeedData:(nullable void(^)(BOOL finished))completed {

    [self.dataManager fetchHomeFeedDataForFeedOption:self.homeNavController.feedFilterOption completion:^(NSError * _Nullable error, NSArray<__kindof KAObject *> * _Nullable feedObjects) {

        if (error != nil) {
            NSLog(@"something went wrong: %@", error.localizedDescription);
            if (completed) completed(NO);
            return;
        }

        NSInteger originalCount = self.contentObjects.count;

        if (self.dataManager.isFirstTimeLoading) self.contentObjects = feedObjects.mutableCopy;
        else {
            if (self.dataManager.isGettingNew) for (MYObject *obj in feedObjects) [self.contentObjects insertObject:obj atIndex:0];
            else if (feedObjects.count > 0) [self.contentObjects addObjectsFromArray:feedObjects];
        }


        if (feedObjects.count > 0) {
            if (self.dataManager.isFirstTimeLoading) [self.tableView reloadData];
            else {
                [self.tableView insertCells:feedObjects forSection:0 startingIndex:self.dataManager.isGettingNew? 0 : originalCount];
            }
        } else if (self.dataManager.isFirstTimeLoading) [self.tableView reloadData];


        if (completed) completed(YES);

    }];

}

注意:

[self.tableView insertCells:feedObjects forSection:0 startingIndex:self.dataManager.isGettingNew? 0 : originalCount];

就是这样:

- (void)insertCells:(nullable NSArray *)cells forSection:(NSInteger)section startingIndex:(NSInteger)start {

    if (!cells) return;

    NSMutableArray *indexPaths = @[].mutableCopy;

    for (id obj in cells) {
        NSInteger index = [cells indexOfObject:obj] + start;
        [indexPaths addObject:[NSIndexPath indexPathForRow:index inSection:section]];
    }

    [self insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];

}

更新2

我的UITableViewCell子类内容是隐藏的ATM(出于发布此帖子的目的,编辑我的所有帖子内容太困难了)。我只是将每个单元格的子视图设置为alpha = 0.f。它只是一个图像视图,一些标签和一些按钮。

控制台中没有约束问题,调用[self.tableView reloadData]时单元格呈现完美,所以也许在插入单元格时我做错了什么......

1 个答案:

答案 0 :(得分:1)

处理UITableView的故障时:

  1. 确保您在主线程上调用UIKit API-启用主线程检查器

enter image description here

对于您而言,可能存在一个问题,即fetchHomeFeedDataForFeedOption:completion:完成块不在主线程上调用。

  1. 您的插入内容绝对是错误的-对UITableView的所有删除/插入/更新/移动调用均应包装在beginUpdates / endUpdates

  2. 您底部的“加载更多”组件可能是一个问题。您需要解决它如何管理表视图的contentSize / contentOffset / contentInset。如果除了操作contentInset以外,它什么都没做-它做错了工作。

尽管很难调试整个解决方案,但我敢肯定选项2和3是关键问题。