Created
June 5, 2026 05:20
-
-
Save unixzii/6db8b31ccecc9be4fd067bcc291bcf1f to your computer and use it in GitHub Desktop.
A minimal project for demonstrating the performance issues in SwiftUI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SwiftUI | |
| struct CellView: View { | |
| let text: String | |
| @State private var flag: Bool = false | |
| var body: some View { | |
| Text(verbatim: text) | |
| .padding() | |
| .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) | |
| .background { | |
| if flag { | |
| Color.primary.opacity(0.1) | |
| } | |
| } | |
| .task(id: text) { | |
| do { | |
| // Simulate a background computation. | |
| try await Task.sleep(for: .milliseconds(100)) | |
| withAnimation(.linear(duration: 0.1)) { | |
| flag = true | |
| } | |
| } catch { | |
| // Handle the cancellation... | |
| } | |
| } | |
| .onChange(of: text) { _, _ in | |
| // Clear the stale computed value. | |
| flag = false | |
| } | |
| } | |
| } | |
| struct NativeListView: NSViewRepresentable { | |
| typealias NSViewType = NSScrollView | |
| typealias Coordinator = _Coordinator | |
| class _Coordinator: NSObject, NSTableViewDelegate { | |
| var dataSource: NSTableViewDiffableDataSource<String, String>? | |
| func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { | |
| return 44 | |
| } | |
| } | |
| func makeCoordinator() -> _Coordinator { | |
| return .init() | |
| } | |
| func makeNSView(context: Context) -> NSScrollView { | |
| let tableView = NSTableView(frame: .zero) | |
| tableView.style = .fullWidth | |
| tableView.headerView = nil | |
| tableView.floatsGroupRows = false | |
| tableView.usesAutomaticRowHeights = true | |
| tableView.backgroundColor = .clear | |
| tableView.delegate = context.coordinator | |
| let column = NSTableColumn( | |
| identifier: NSUserInterfaceItemIdentifier(rawValue: "Column") | |
| ) | |
| tableView.addTableColumn(column) | |
| let dataSource = NSTableViewDiffableDataSource<String, String>( | |
| tableView: tableView | |
| ) { tableView, _, _, itemIdentifier in | |
| let identifier = NSUserInterfaceItemIdentifier(rawValue: "Cell") | |
| if let view = tableView.makeView( | |
| withIdentifier: identifier, | |
| owner: nil | |
| ) as? NSHostingView<CellView> { | |
| view.rootView = CellView(text: itemIdentifier) | |
| return view | |
| } | |
| let view = NSHostingView<CellView>(rootView: .init(text: itemIdentifier)) | |
| view.identifier = identifier | |
| return view | |
| } | |
| context.coordinator.dataSource = dataSource | |
| var snapshot = NSDiffableDataSourceSnapshot<String, String>() | |
| snapshot.appendSections(["Root"]) | |
| snapshot.appendItems((0..<1000).map { "Item \($0)" }, toSection: "Root") | |
| dataSource.apply(snapshot, animatingDifferences: false) | |
| let scrollView = NSScrollView() | |
| scrollView.verticalScrollElasticity = .allowed | |
| scrollView.horizontalScrollElasticity = .none | |
| scrollView.hasVerticalScroller = true | |
| scrollView.hasHorizontalScroller = false | |
| scrollView.borderType = .noBorder | |
| scrollView.documentView = tableView | |
| return scrollView | |
| } | |
| func updateNSView(_ nsView: NSScrollView, context: Context) { | |
| } | |
| } | |
| @main | |
| struct PerfIssueDemoApp: App { | |
| var body: some Scene { | |
| WindowGroup { | |
| NativeListView() | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment