使用带有autolayout的NSFetchedResultsController追加或更新UITableView时阻止滚动

时间:2014-12-23 23:58:01

标签: ios uitableview autolayout nsfetchedresultscontroller

我有一个聊天应用程序,它使用核心数据Messages表支持单节UITableViewController。基于推送消息,我更新消息的状态或附加新消息。当新消息到达时,我想滚动到表格的底部。每个单元格都有可变高度,由自动布局驱动,使用:

self.tableView.estimatedRowHeight = 76
self.tableView.rowHeight = UITableViewAutomaticDimension
  1. 我在viewDidLoad中加载NSFetchRequest(),它从核心数据表加载消息,然后跳转到viewDidAppear中的最后一条消息。这在从Xcode运行时可以正常工作,但如果我在iPhone上启动应用程序,它不会跳转到最后一条消息,而是在中间某处。此外,如果我将消息推迟到主线程,它仍然无法正常工作。但是,如果我插入这样的小延迟,它总能正常工作:

    override func viewDidAppear(animated: Bool) {
      super.viewDidAppear(animated)
    
      // not sure why this delay is needed
    
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.001 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
        self.scrollToLastMessage()
      }
    }
    

    当然,我不喜欢有一个固定的延迟,特别是我不明白的。是否有一个特定的事件我应该挂钩滚动到最后一条消息?

  2. 更令人烦恼的是,我找不到让NSFetchResultsController .Insert(append)或.Update行的方法,而UITableViewController不会滚动到另一个位置。我已经尝试捕获和恢复contentOffset,我必须做动画:假以防止非常搞砸的动画,但桌子仍然有可见的滚动闪烁。我已经为整个表尝试了reloadData(),reloadRowsAtIndexPaths()只是更新相关的单元格,有或没有beginUpdates()/ endUpdates()。我也尝试过scrollToRowAtIndexPath(lastRow)。无论如何,我都无法在没有UITableView自动滚动的情况下使用这个简单的更新。它似乎用动画将更改的行滚动到屏幕中间,之后我必须将其滚动回原来的位置。有没有其他人注意到这一点?这是否滚动NSFetchResultsController的一个工件,一个"功能" UITableViewController的结果或使用UITableViewAutomaticDimension的结果?

    到目前为止,我获得了以下最佳效果,但有明显的闪烁。

    func controllerDidChangeContent(controller: NSFetchedResultsController!) {
      self.tableView.reloadData()
    }
    
    private func scrollToLastMessage() {
      dispatch_async(dispatch_get_main_queue()) {
    
        // without the check below, this oddly doesn't scroll to the right place (autolayout issue?)
    
        if self.tableView.contentSize.height > self.tableView.frame.size.height {
          let offset = CGPoint(x: 0, y: self.tableView.contentSize.height - self.tableView.frame.size.height)
          self.tableView.setContentOffset(offset, animated: false)
        }
      }
    }
    
  3. 我在使用UITableViewAutomaticDimension时注意到最后一行的偏移量发生了变化。例如,如果我一次要求偏移量,为了跳转到正确的contentOffset来显示它,contentOffset可以自发地改变,因为UITableViewController探测其他单元格的高度并滚动。有办法防止这种情况吗?即,要让UITableViewAutomaticDimension始终测量单元格的实际高度而不是估计的高度,这样我就不必实现rowHeight方法了?如上所述,我还尝试过scrollToRowAtIndexPath(lastRow),但它具有相同的奇怪滚动行为。

0 个答案:

没有答案