项目中,需要在进入 UIViewController 后对它里面的 UITableView 滑动到最底部,那么需要把代码写在 viewDidLoad 中。

下面这一行代码要使得 previewTable 这个UITableView 滑动到最底部的位置。(home.tickTasks 是我对代码中这个 tableView 的数据源,可根据实际需要设置)


self.previewTable.scrollToRow(at: IndexPath.init(row: (Home.tickTasks.count - 1), section: 0), at: .bottom, animated: false)

但是,不管是否需要动画,以上代码总是不能准确地滑动到指定位置,滑动的动作需要一点点时间。

以下使用同步机制来等待一小段时间。

DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
            self.previewTable.scrollToRow(at: IndexPath.init(row: (Home.tickTasks.count - 1), section: 0), at: .bottom, animated: false)
        }

猜想,是因为代码控制对 tableView 的滑动需要在 tableView 初始化好并且把 cell 的数据加载进来之后,如下代码,若这样写,则会出现 tableView 划不到最底部的情况。

override func viewDidLoad() {
        super.viewDidLoad()
        
        bindTableView()    // 配置 tableView 的 dataSource、delegate 等信息
       
        loadFromCoreData() // 加载数据到 tableViewCell 中
        
        self.previewTable.scrollToRow(at: IndexPath.init(row: (Home.tickTasks.count - 1), section: 0), at: .bottom, animated: false)
        // 此时存在数据未加载完成但滑动动作异步执行,所以未滑到最底部,滑动就被终止了。
    }

问题出在于未加载完成就进行界面的滑动,所以我们让对界面滑动稍微延迟 0.01 秒,如下代码所示

override func viewDidLoad() {
        super.viewDidLoad()
        bindTableView()
     
        loadFromCoreData()
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
            self.previewTable.scrollToRow(at: IndexPath.init(row: (Home.tickTasks.count - 1), section: 0), at: .bottom, animated: false)
        } 
    }

此时就可以滑动到最底部了,但还有一个小问题,上面的 row 为 Home.tickTasks.count - 1,当 count 为 0 时程序会闪退,因为 index 越界了,所以像下面一样预先判断 count 即可解决问题。

override func viewDidLoad() {
        super.viewDidLoad()
        bindTableView()
        
        loadFromCoreData()
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
            if Home.tickTasks.count > 0 {
                self.previewTable.scrollToRow(at: IndexPath.init(row: (Home.tickTasks.count - 1), section: 0), at: .bottom, animated: false)
            }
        }
    }

ZanxinZ
5 声望0 粉丝

iOS 开发,软件开发。