在使用UIHostingConfiguration的混合UIKit/SwiftUI设置中,如何在单元格内容调整大小时防止UITableView的内容跳动?

移动开发 2026-07-07

我正在尝试通过 UITableViewUIHostingConfiguration 来显示单元格的内容,重写我的SwiftUI滚动视图。设置本来很简单,但我在调整单元格大小方面遇到了一个阻碍。

每当单元格的内容在垂直方向增长时,表格视图就会跳动不稳,大家有什么想法来解决这个问题吗? 参考请见附上的视频:

https://imgur.com/a/KcHVh2R

我已将示例项目上传到GitHub:
https://github.com/wiencheck/SwiftUITableViewPOC

主要内容位于 TableViewPOC/TableViewController.swift

解决方案

看完你的代码后,我发现了以下问题:

text changes
    ↓
SwiftUI invalidates Text
    ↓
UIHostingConfiguration recalculates intrinsic height
    ↓
UITableView asks for new row height
    ↓
your controller receives objectWillChange
    ↓
update()
    ↓
dataSource.apply(snapshot)
    ↓
UITableView performs another layout pass
viewModel.objectWillChange
    .receive(on: DispatchQueue.main)
    .sink { [weak self] in
        self?.update()
    }
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)

这就是造成问题的原因。

为了解决这个问题

ViewModel.swift

import Combine

final class ViewModel: ObservableObject {

    let sectionsChanged = PassthroughSubject<Void, Never>()

    // Call this whenever sections are added/removed/reordered
    func notifySectionsChanged() {
        sectionsChanged.send()
    }
}

TableViewController.swift,将以下内容替换为:

viewModel.objectWillChange
    .receive(on: DispatchQueue.main)
    .sink { [weak self] in
        self?.update()
    }
    .store(in: &cancellables)

为:

viewModel.sectionsChanged
    .receive(on: DispatchQueue.main)
    .sink { [weak self] in
        self?.update()
    }
    .store(in: &cancellables)

然后每当你的sections数组发生变化:

sections.append(newSection)
sectionsChanged.send()

或:

sections.removeAll { $0.id == id }
sectionsChanged.send()

同时将以下内容修改为:

.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)

为:

.frame(maxWidth: .infinity, alignment: .topLeading)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章