【ios】SwiftUI 混用 UIKit 的 Bug 办理:UITableView 无法滚动到底部

[复制链接]
发表于 2026-1-11 22:05:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
标题形貌

在 SwiftUI 中嵌套利用 UIKit 的 UITableView 时,你大概会遇到一个常见的 Bug:UITableView 的高度没有准确设置,导致内容无法正常滚动,尤其是滚动到页面底部时。
核心标题在于 SwiftUI 和 UIKit 的布局机制差异。SwiftUI 利用声明式布局体系,而 UIKit 利用传统的视图条理布局。假如没有明白告诉 UITableView 应该占用多少高度,UIKit 中的 UITableView 大概会默认按照父视图的尺寸盘算,忽略 SwiftUI 布局中的其他组件。因此,UITableView 的高度和滚动活动就会出现标题。
办理思绪

为了让 UITableView 在 SwiftUI 布局中可以大概准确滚动到底,我们须要:

  • 动态获取 SwiftUI 中的可用高度,通过 SwiftUI 的 GeometryReader 盘算当前布局的高度。
  • 将高度通报给 UIKit 中的 UITableView,确保它根据父视图的高度动态调解。
以下是一个办理该标题的demo示例

1. 利用 UIViewControllerRepresentable 桥接 SwiftUI 和 UIKit

我们起首须要创建一个桥接类,让 SwiftUI 可以大概嵌套 UIKit 组件。在这个桥接类中,我们吸取从 SwiftUI 获取的高度,然后在 UIKit 组件中利用这个高度动态调解 UITableView 的巨细。
  1. import SwiftUI
  2. struct MyTableViewWrapper: UIViewControllerRepresentable {
  3.     var height: CGFloat // 接收传递过来的高度
  4.     func makeUIViewController(context: Context) -> MyTableViewController {
  5.         let controller = MyTableViewController()
  6.         controller.height = height // 设置高度
  7.         return controller
  8.     }
  9.     func updateUIViewController(_ uiViewController: MyTableViewController, context: Context) {
  10.         uiViewController.height = height // 动态更新高度
  11.     }
  12. }
复制代码
MyTableViewWrapper 作为 SwiftUI 和 UIKit 的桥接类,它允许我们将 SwiftUI 的布局数据(比如高度)通报给 UIKit 中的 UITableView。
2. 在 UIViewController 中调解 UITableView 的高度

在自界说的 UIViewController 中,我们利用传入的高度来设置 UITableView 的 frame,如许可以确保 UITableView 的巨细根据 SwiftUI 的布局进办法态调解。
  1. import UIKit
  2. class MyTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
  3.     var height: CGFloat = 0 // 用于接收传进来的高度
  4.    
  5.     override func viewDidLoad() {
  6.         super.viewDidLoad()
  7.         // 创建 UITableView,并根据传入的高度调整它的大小
  8.         let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: height), style: .plain)
  9.         tableView.dataSource = self
  10.         tableView.delegate = self
  11.         view.addSubview(tableView)
  12.     }
  13.     // UITableViewDataSource 协议实现
  14.     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  15.         return 20
  16.     }
  17.     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  18.         let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
  19.         cell.textLabel?.text = "Row \(indexPath.row)"
  20.         return cell
  21.     }
  22. }
复制代码
在这个自界说的 UIViewController 中,UITableView 的高度由外部传入并动态调解,如许就克制了 UITableView 默认假设本身占据全屏的标题。
3. 利用 GeometryReader 获取 SwiftUI 中的高度

接下来,我们须要在 SwiftUI 布局中利用 GeometryReader 来动态获取可用的高度,并将其通报给 UIKit 的 UITableView。
  1. struct ContentView: View {
  2.     var body: some View {
  3.         GeometryReader { geometry in
  4.             VStack {
  5.                 Text("这里是一些顶部内容")
  6.                     .padding()
  7.                 // 将当前视图的高度传递给 UIKit 中的 TableView
  8.                 MyTableViewWrapper(height: geometry.size.height * 0.6) // 比如占屏幕60%高度
  9.                 Spacer()
  10.             }
  11.             .padding()
  12.         }
  13.     }
  14. }
复制代码
在这个布局中,GeometryReader 会动态盘算当前视图的高度,并将这个高度通报给 MyTableViewWrapper,从而确保 UITableView 根据父视图的高度准确调解。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表