【问题标题】:scrollToRowAtIndexPath always scrolls from the top instead from current offsetscrollToRowAtIndexPath 总是从顶部滚动而不是从当前偏移量
【发布时间】:2015-09-09 09:54:09
【问题描述】:

在我的UITableView 中,我使用一种方法滚动到最后一个单元格:

WLNetworkClient.sharedClient().createCommentWIthText(commentTextView.text, forItem: item) { error in

    defer {
        UIAlertController.showAlertFromError(error)
    }

    if error == nil {
        self.fetchedResultsController.fetchRequest.fetchLimit += 1
        try! self.fetchedResultsController.performFetch()
        self.tableView.reloadData()
        self.scrollTableViewToBottom()
    }
}

private func scrollTableViewToBottom() {

    tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: fetchedResultsController.fetchedObjects!.count - 1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)
}

但这并没有按预期工作,因为即使我在倒数第二个单元格上,表格也总是从顶部滚动。如何解决这个问题?

【问题讨论】:

  • 请在该行附近显示更多代码。
  • 更新了问题
  • 你试过UITableViewScrollPosition.none吗?
  • 感谢您的回复,但这里没有任何效果。问题不在于何时,而在于为什么从顶部开始?也许这是 Xcode 7 的问题?
  • Reload 不应该滚动到任何地方,除非它不能保持显示的原始单元格。如果你注释掉 fetch 并且滚动到底部(基本上什么都不做)它仍然滚动到顶部吗?我会剥离代码,看看你是否可以达到重新加载不影响位置的地步。

标签: ios swift uitableviewautomaticdimension


【解决方案1】:

dosdos 回答在 Swift 2 中为我工作 添加小更新

声明 ivar

var heightAtIndexPath = NSMutableDictionary()

在函数viewDidLoad()中

func viewDidLoad() {
  .... your code
  self.tableView.rowHeight = UITableViewAutomaticDimension
}

然后添加以下2个方法:

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
   let height = self.heightAtIndexPath.objectForKey(indexPath)
   if ((height) != nil) {
     return CGFloat(height!.floatValue)
   } else {
    return UITableViewAutomaticDimension
   }
 }

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
  let height = cell.frame.size.height
  self.heightAtIndexPath.setObject(height, forKey: indexPath)
}

SWIFT 3:

var heightAtIndexPath = NSMutableDictionary()

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    let height = self.heightAtIndexPath.object(forKey: indexPath)
    if ((height) != nil) {
        return CGFloat(height as! CGFloat)
    } else {
        return UITableViewAutomaticDimension
    }
}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let height = cell.frame.size.height
    self.heightAtIndexPath.setObject(height, forKey: indexPath as NSCopying)
}

【讨论】:

  • 你是我的救星,我没想到单元格的自动标注会导致这个问题。谢谢!
【解决方案2】:

扩展 ZaEeM ZaFaR 很好的答案:

目标 C

NSMutableDictionary *heightAtIndexPath;
heightAtIndexPath = [[NSMutableDictionary alloc] init];

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSNumber *height = [heightAtIndexPath objectForKey:indexPath];
    if(height) {
        return height.floatValue;
    } else {
        return UITableViewAutomaticDimension;
    }
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    [heightAtIndexPath setObject:@(cell.frame.size.height) forKey:indexPath];
}

【讨论】:

    【解决方案3】:

    我认为问题在于您在 tableView 更新之前滚动(self.tableView.reloadData())。 尝试延迟滚动:

         dispatch_async(dispatch_get_main_queue()) {
             self.scrollTableViewToBottom()
        }
    

    或者强制tableView更新:

        self.tableView.reloadData()
        self.tableView.layoutIfNeeded()
        self.scrollTableViewToBottom()
    

    【讨论】:

      【解决方案4】:

      这里讨论了这个问题:How to tell when UITableVIew has completed ReloadData?

      将您的代码更改为:

      self.tableView.reloadData()
      self.tableView.layoutIfNeeded()
      self.scrollTableViewToBottom()
      

      layoutIfNeeded 强制表重新加载立即发生。全部在链接中解释。

      【讨论】:

        【解决方案5】:

        为了更快捷,我会简化上面介绍的 Swift 3 版本:

            var heightAtIndexPath = [IndexPath: CGFloat]()
        
            func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
                if let height = self.heightAtIndexPath[indexPath] {
                    return height
                }
                return UITableViewAutomaticDimension
            }
        
            func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
                let height = cell.frame.size.height
                self.heightAtIndexPath[indexPath] = height
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-21
          • 1970-01-01
          • 1970-01-01
          • 2018-05-07
          • 1970-01-01
          • 2014-10-24
          相关资源
          最近更新 更多