现在在做一个类似聊天的界面,需求是当进入聊天列表的时候,tableView自动滚动到最后一条聊天记录。
首先,tableView滚动到底部通用的是这两种方法:
1.tableView.setContentOffset(CGPoint(x:0, y:tableView.contentSize.height - tableView.bounds.size.height), animated: false)
2.if self.messageModelArray.count > 0 {
tableView.scrollToRow(at: IndexPath(row: self.messageModelArray.count - 1, section: 0), at: .bottom, animated: false)
}
开始想用第一种方法实现来,但是tableView的contenSize是随着加载cell的个数而发生变化的,所以选择的第二种方法。
那么在什么时机去调用tableView的scrollToRow方法呢,这是重点。首先在viewDidLoad和viewWillAppear方法中肯定是不行的,因为tableView还没有加载完成。另外,在viewDidAppear方法中倒是可以实现,但是会有一个明显的滑动过程,即使animated设置为false也会有滑动的过程,用户体验不好。
最后想到的办法是在numberOfRowsInSection方法中去调用tableView的scrollToRow方法,并且加一个判断,只有在初始化的时候去调用,之后再reload的时候就不调用了。这里需要加一个延时,否则会造成死循环,为啥会造成死循环还没有搞明白,尴尬。。。 最后贴代码,如下:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isScrollBottom { //只在初始化的时候执行
let popTime = DispatchTime.now() + 0.005 //延迟执行5毫秒
DispatchQueue.main.asyncAfter(deadline: popTime) {
if self.messageModelArray.count > 0 {
tableView.scrollToRow(at: IndexPath(row: self.messageModelArray.count - 1, section: 0), at: .bottom, animated: false)
}
}
}
return self.messageModelArray.count
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.isScrollBottom = false
}