如何纯代码为UITableView添加UIRefreshControl且保留大标题效果
纯代码实现大标题模式下正常工作的UITableView下拉刷新
问题触发条件
- 页面结构:
UITableView嵌套在UINavigationController中 - 实现方式:全代码布局,不使用Storyboard
- 异常表现:直接设置
tableView.refreshControl = refreshControl后,下拉无法触发刷新控件;移除navigationBar.prefersLargeTitles = true配置后刷新功能恢复正常,但需要保留大标题效果
核心原因
大标题模式下导航栏会自动调整滚动视图的内容内边距,若刷新控件绑定顺序错误、层级添加错误,会导致刷新控件的手势识别被导航栏层级拦截,无法响应下拉动作。
正确实现代码
第一步:优先配置导航栏大标题
大标题配置必须写在tableView和refreshControl初始化之前,保证内边距计算逻辑正确:
// 全局开启导航栏大标题 navigationController?.navigationBar.prefersLargeTitles = true // 配置当前页面的大标题显示规则 navigationItem.largeTitleDisplayMode = .always // 若自定义导航栏外观,需保持导航栏半透明属性为true,否则内边距计算异常 navigationController?.navigationBar.isTranslucent = true
第二步:初始化并配置UITableView
private let tableView = UITableView(frame: .zero, style: .plain) // 在viewDidLoad中添加布局代码 override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white // 设置tableView布局 tableView.frame = view.bounds tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // 开启系统自动调整内容内边距 tableView.contentInsetAdjustmentBehavior = .automatic view.addSubview(tableView) }
第三步:绑定UIRefreshControl
// 初始化刷新控件 private let refreshControl = UIRefreshControl() // 写在viewDidLoad里、tableView添加到父视图之后 override func viewDidLoad() { super.viewDidLoad() // ...省略上面的tableView配置代码 // 给刷新控件绑定触发事件 refreshControl.addTarget(self, action: #selector(pullToRefreshAction), for: .valueChanged) // 直接给tableView的refreshControl属性赋值,不要手动addSubview tableView.refreshControl = refreshControl } // 刷新事件处理 @objc private func pullToRefreshAction() { // 执行网络请求、数据加载逻辑 loadNewData { [weak self] in guard let self = self else { return } // 数据加载完成后结束刷新 self.refreshControl.endRefreshing() self.tableView.reloadData() } }
常见避坑项
- 禁止手动调用
tableView.addSubview(refreshControl):iOS 10 及以上系统由refreshControl属性自动管理控件层级,手动添加会导致大标题模式下手势拦截 - 禁止颠倒配置顺序:必须先完成大标题配置,再添加tableView、最后绑定refreshControl,顺序错误会导致内边距计算偏差
- 不要手动修改
tableView.contentInset的top值:大标题模式下top内边距由系统自动计算,手动修改会导致刷新控件位置偏移、无法触发 - 若页面存在滚动到顶部的逻辑,优先使用
tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true),不要直接修改contentOffset
内容的提问来源于stack exchange,提问作者HAHALOSAH
相关产品推荐
相关产品推荐

