加载tweet时更新UITableView高度

时间:2017-06-24 11:03:52

标签: ios uitableview twitter twitterkit

我有UITableViewCell,其中包含带有自动布局的TWTRTweetView。我正在加载这样的推文:

Constraints

Height contraint details

- (void)loadTweetWithId:(NSString *)tweetId {

    if (mTweetId == nil || ![mTweetId isEqualToString:tweetId]) {
        mTweetId = tweetId;
        [[[TWTRAPIClient alloc] init] loadTweetWithID:tweetId completion:^(TWTRTweet *tweet, NSError *error) {
            if (tweet) {
                NSLog(@"Tweet loaded!");
                [mTweetView configureWithTweet:tweet];
                [mTweetView setShowActionButtons:YES];
                //[mTweetView setDelegate:self];
                [mTweetView setPresenterViewController:self.viewController];
                [mTweetView setNeedsLayout];
                [mTweetView layoutIfNeeded];
                [mTweetView layoutSubviews];
                hc.constant = mTweetView.frame.size.height;
                [self updateConstraints];
                [self layoutIfNeeded];
                [self layoutSubviews];
                [self.tableView setNeedsLayout];
                [self.tableView layoutIfNeeded];
                [self.tableView layoutSubviews];
            } else {
                NSLog(@"Tweet load error: %@", [error localizedDescription]);
            }
        }];
    }
}

当推文加载的单元格没有调整大小时,除非我将其向外滚动并将其向后滚动。我已经尝试了几种方法,你可以在代码片段中看到。但不是这些作品。我的表格视图使用全自动布局方法,该方法不会为行功能实现单元格高度。我该如何解决这个问题?

更新

使用:

[self.tableView beginUpdates];
[self.tableView endUpdates];

是不可能的,因为当我这样做时,所有细胞都被重新绘制并且发生非常大的跳跃并且这是不可接受的。我也确认推文完成块在主线程中运行。

Jump video

更新2:

我还尝试使用tweet id缓存tweet视图并重新加载相关索引路径的单元格,并为tweet id提供相同的tweet视图。单元格高度已更正,但在向外滚动之前不会显示。

更新3:

我在单元格的xib中为tweet视图提供约束,并且连接了高度约束。所以这不是一个主要的线程问题。我还提到在索引处重新加载特定单元格并不起作用。

在使用其他解决方案时,我看到了一些使用TwitterKit的示例TWTRTweetTableViewCell代码但正在预加载推文以配置单元格。所以我也做了同样的事情。这当然是一种解决方法。

3 个答案:

答案 0 :(得分:0)

在使用

加载推文后尝试重新加载该特定单元格
- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths 
              withRowAnimation:(UITableViewRowAnimation)animation;

答案 1 :(得分:0)

我有类似的问题,我通过在dispatch_async中添加所有代码来确保它在主线程上运行,从而解决了这个问题。

 dispatch_async(dispatch_get_main_queue(), ^{ 
      /*CODE HERE*/
 });

所以你的代码应该是这样的:

- (void)loadTweetWithId:(NSString *)tweetId {

  if (mTweetId == nil || ![mTweetId isEqualToString:tweetId]) {
      mTweetId = tweetId;
    [[[TWTRAPIClient alloc] init] loadTweetWithID:tweetId completion:^(TWTRTweet *tweet, NSError *error) {

        dispatch_async(dispatch_get_main_queue(), ^{ 

        if (tweet) {
            NSLog(@"Tweet loaded!");
            [mTweetView configureWithTweet:tweet];
            [mTweetView setShowActionButtons:YES];
            //[mTweetView setDelegate:self];
            [mTweetView setPresenterViewController:self.viewController];
            [mTweetView setNeedsLayout];
            [mTweetView layoutIfNeeded];
            [mTweetView layoutSubviews];
            hc.constant = mTweetView.frame.size.height;
            [self updateConstraints];
            [self layoutIfNeeded];
            [self layoutSubviews];
            [self.tableView setNeedsLayout];
            [self.tableView layoutIfNeeded];
            [self.tableView layoutSubviews];
        } else {
            NSLog(@"Tweet load error: %@", [error localizedDescription]);
        }

    });

    }];
  }
 }

答案 2 :(得分:0)

更新答案:

你做错了一些可能导致(或至少有助于)跳跃的事情:

  • 永远不要自己致电layoutSubviews 它是系统调用以解决约束的方法。在连续拨打setNeedsLayoutlayoutIfNeeded时会自动触发。

  • 这同样适用于updateConstraints系统在布局过程中调用它。您可以随后调用setNeedsUpdateContraintsupdateConstraintsIfNeeded来手动触发它。此外,只有在自定义视图(或单元格)中实际实现(覆盖)该方法时才会产生影响。

  • 当您在视图上调用layoutIfNeeded时,它会布置其子视图。因此,当您更改约束mTweetView的约束的常量时,它可能不会产生任何效果(除非在触发的布局传递期间视图层次结构无效)。您需要在layoutIfNeeded的超级视图上调用mTweetView,这是该单元格的内容视图(根据您添加到帖子中的屏幕截图判断):

    [contentView layoutIfNeeded];
    

此外,还有一件事需要注意,这也可能导致闪烁:

  • 表视图中的单元格正在被回收。每次重复使用一个单元格时,您都会加载一条新的推文。我猜它来自异步网络请求?如果是这样,那么您为该单元实例加载的第一条推文中的完成块可能会在您为该(循环)单元格加载的第二条推文完成之后返回或者你的互联网连接真的很慢。确保取消请求或在重复使用单元格时以某种方式使其无效(prepareForReuse方法)。

请确保您已修复所有这些问题,并查看动画现在是否按预期工作。 (我在下面的原始答案仍然有效。)

原始答案:

我很确定

[self.tableView beginUpdates];
[self.tableView endUpdates];

唯一的方法让细胞在显示时自动调整大小。

原因:

对于历史性的性能原因,UITableView始终适用于固定高度的单元格(内部)。即使通过设置estimatedRowHeight等使用自调整单元格,表格视图也会计算单元格出列时的高度,即之前它出现在屏幕上。然后,它会向单元格添加一些内部约束,使其具有固定宽度固定高度,它与自动布局计算的大小相匹配。

这些内部约束仅在需要时更新,即重新加载行时。现在当你在你的单元格中添加任何约束时,你将会&#34;战斗&#34;针对具有必需优先级(又称1000)的内部约束。换句话说:没有办法获胜!

更新这些内部(固定)单元格约束的唯一方法是告诉表视图它应该。据我所知,唯一公开(记录)的API是

- (void)beginUpdates;
- (void)endUpdates;

所以剩下的唯一问题是:

为什么这种方法不适合您?

我认为在重新调整单元格之后重新绘制单元格是合法的。展开单元格以显示比在需要之前重新绘制单元格之前更长的推文!

您可能不会(并且不应该)始终调整所有可见单元格。 (这对用户来说会很混乱......)