什么时候UITableView的contentSize被设置?

我在UIScrollView有一个不滚动的UITableView 。 我将UITableView的框架大小设置为其内容大小。

当我向UITableView添加一行时,我在UITableView调用了insertRowsAtIndexPaths:withRowAnimation 然后我调用一个方法来调整UITableView的框架:

 - (void)resizeTableViewFrameHeight { // Table view does not scroll, so its frame height should be equal to its contentSize height CGRect frame = self.tableView.frame; frame.size = self.tableView.contentSize; self.tableView.frame = frame; } 

这似乎虽然contentSize尚未更新在这一点上。 如果我手动计算框架在上面的方法基于行数和部分的数量,然后该方法正常工作。

我的问题是,我怎样才能让UITableView更新其contentSize ? 我想我可以调用reloadData ,这可能会做到这一点,但是当我插入一个单元格时,重新加载整个表格似乎效率低下。

您可以强制UITableView通过调用UITableView上的layoutIfNeeded来计算内容的大小。

一个UITableViewController子类的例子,它应该在容器视图中具有可变的大小:

 - (CGSize)preferredContentSize { // Force the table view to calculate its height [self.tableView layoutIfNeeded]; return self.tableView.contentSize; } 

更新2016-07-28这是一个未经testing的同样事情的Swift示例。 它应该工作,但如果它不请,请留下评论。 可能有更好或更习惯的方法来做到这一点。 不幸的是我对Swift不是很熟悉。

 override var preferredContentSize: CGSize { get { self.tableView.layoutIfNeeded() return self.tableView.contentSize } set {} } 

虽然我不喜欢KVO(Key-Value Observing),但是确实知道你的表的contentSize发生了什么变化(而不是在一堆随机的地方调用你的更新方法)是一个相当好的方法。 它使用起来相当简单(虽然有点隐晦和隐含)。 要观察表的contentSize上的更改,请执行以下操作:

1)成为你的表的contentSize属性的观察者,如下所示:

 [self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:NULL]; 

这通常在保存tableView的视图控制器(例如viewDidLoad: )中完成。

2)执行KVO观测方法并进行所需的更改:

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if(object == self.tableView && [keyPath isEqualToString:@"contentSize"]) { // perform your updates here } } 

3)删除你的视图控制器作为观察者在某个逻辑点(我称之为dealloc )。 你这样做是这样的:

 - (void)dealloc { [self.tableView removeObserver:self forKeyPath:@"contentSize"]; } 

尝试这个:

 - (void)resizeTableViewFrameHeight { UITableView *tableView = self.tableView; CGRect frame = tableView.frame; frame.size.height = [tableView sizeThatFits:CGSizeMake(frame.size.width, HUGE_VALF)].height; tableView.frame = frame; } 
  1. 添加观察者(在我的示例viewDidLoad

     tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil) 
  2. 观察价值

     override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if let obj = object as? UITableView { if obj == self.tableView && keyPath == "contentSize" { if let newSize = change?[NSKeyValueChangeKey.newKey] as? CGSize { //do stuff here } } } } 
  3. 不需要时移除观察者

     deinit { self.tableView.removeObserver(self, forKeyPath: "contentSize") } 

您可以更改页脚的框架。 我之前打电话animation出现的页脚。

 if self.newTableView.contentSize.height < self.newTableView.frame.height { let additionalHeight: CGFloat = self.newTableView.frame.height - self.newTableView.contentSize.height let tableFooterView = self.newTableView.tableFooterView! let x = tableFooterView.frame.origin.x let y = tableFooterView.frame.origin.y + additionalHeight let width = tableFooterView.frame.width let height = tableFooterView.frame.height tableFooterView.frame = CGRect(x: x, y: y, width: width, height: height) } 

这对我来说,解决在添加/删除行后得到正确大小的tableview的问题

运用

  tableView.layoutIfNeeded() 

和设置

  tableView.estimatedRowHeight = UITableViewAutomaticDimension