Swift:为表格分区表头添加UIRefreshControl不显示问题排查
Hey,我来帮你排查下UIRefreshControl不显示的问题,这里有几个关键的误区你踩中了:
1. UIRefreshControl的容器与尺寸问题
你把UIRefreshControl加到了一个尺寸只有(width: tableView.bounds.size.width - 20, height: 40)的UIScrollView里,但UIRefreshControl的默认高度大约是60pt,这个小容器直接把它裁剪掉了,所以自然看不到。
更重要的是:UIRefreshControl是专门设计给UIScrollView(包括UITableView)的内置控件,它需要通过scrollView.refreshControl属性来绑定,而不是用addSubview添加到视图层级里——这也是你尝试view.refreshControl = refreshCtrl没生效的原因,因为这个小scrollView根本没有滚动空间,UIRefreshControl的显示逻辑依赖于scrollView的滚动偏移。
2. 错误的使用场景
section header是UITableView的固定(或随列表滚动但不可独立滚动)视图,把UIRefreshControl放在这里完全违背了它的设计初衷——它是用来触发整个滚动视图的下拉刷新,而不是在一个固定小视图里显示动画。
针对你的需求,两种正确的实现方式
需求1:让整个列表支持下拉刷新,且在appsAreGettingInstalled时显示刷新状态
直接把UIRefreshControl绑定到tableView本身:
override func viewDidLoad() { super.viewDidLoad() // 初始化并绑定refreshControl到tableView let refreshCtrl = UIRefreshControl() refreshCtrl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged) tableView.refreshControl = refreshCtrl // 根据标志位控制刷新状态 if appsAreGettingInstalled { refreshCtrl.beginRefreshing() // 可以额外设置tableView的section header文本,比如自定义header显示提示 } else { refreshCtrl.endRefreshing() } } @objc private func handleRefresh() { // 这里写你的刷新逻辑,比如等待安装完成 DispatchQueue.main.asyncAfter(deadline: .now() + 2) { self.tableView.refreshControl?.endRefreshing() self.appsAreGettingInstalled = false self.tableView.reloadData() } } // 自定义section header显示提示文本(如果需要) override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 40)) // 设置header背景色等样式 if appsAreGettingInstalled { let textAttribs: [NSAttributedString.Key: Any] = [ .foregroundColor: UIColor.white, .font: UIFont(name: "Arial", size: 16.0)! ] let titleString = NSAttributedString(string: "Apps are getting installed", attributes: textAttribs) let lbl = UILabel(frame: CGRect(x: 10, y: 0, width: tableView.bounds.width - 20, height: 40)) lbl.attributedText = titleString headerView.addSubview(lbl) } return headerView }
需求2:仅在section header里显示加载动画(不需要下拉刷新交互)
这种情况UIRefreshControl不是合适的选择,改用UIActivityIndicatorView更合适:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { // 给header足够的高度容纳标签和指示器 let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 60)) headerView.backgroundColor = // 设置你需要的背景色 let textAttribs: [NSAttributedString.Key: Any] = [ .foregroundColor: UIColor.white, .font: UIFont(name: "Arial", size: 16.0)! ] if appsAreGettingInstalled { // 添加提示标签 let titleString = NSAttributedString(string: "Apps are getting installed", attributes: textAttribs) let lbl = UILabel(frame: CGRect(x: 10, y: 10, width: tableView.bounds.width - 60, height: 40)) lbl.attributedText = titleString headerView.addSubview(lbl) // 添加加载指示器 let activityIndicator = UIActivityIndicatorView(style: .white) activityIndicator.frame = CGRect(x: tableView.bounds.width - 50, y: 10, width: 40, height: 40) activityIndicator.startAnimating() headerView.addSubview(activityIndicator) } return headerView }
简单总结下:UIRefreshControl是绑定到可滚动容器的全局刷新控件,不能放在固定的section header里当普通动画用。根据你的实际需求选上面其中一种实现方式就能解决问题啦~
内容的提问来源于stack exchange,提问作者phoebus

