SwiftUI List DisclosureGroup Rendering Issues on macOS 13 & 14

Issue Description

Whenever the first item in the List is a DisclosureGroup, all subsequent disclosure groups work fine. However, if the first item is not a disclosure group, the disclosure groups in subsequent items do not render correctly.

This issue does not occur in macOS 15, where everything works as expected.

Has anyone else encountered this behavior, or does anyone have a workaround for macOS 13 & 14?

I’m not using OutlineGroup because I need to bind to an isExpanded property for each row in the list.

Reproduction Steps

I’ve created a small test project to illustrate the issue:

  1. Press “Insert item at top” to add a non-disclosure item at the start of the list.
  2. Then, press “Append item with sub-item” to add a disclosure group further down.
  3. The disclosure group does not display correctly. The label of the disclosure group renders fine, but the content of the disclosure group does not display at all.
  4. Press "Insert item at top with sub-item" and the list displays as expected.

Build Environment

  • macOS 15.3.2 (24D81)
  • Xcode Version 16.2 (16C5032a)

Issue Observed

  • macOS 13 & 14 (bug occurs)
  • macOS 15 (works correctly)

Sample Code

import SwiftUI
class ListItem: ObservableObject, Hashable, Identifiable {
var id = UUID()
@Published var name: String
@Published var subItems: [ListItem]?
@Published var isExpanded: Bool = true
init(
name: String,
subjobs: [ListItem]? = nil
) {
self.name = name
self.subItems = subjobs
}
static func == (lhs: ListItem, rhs: ListItem) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
struct ContentView: View {
@State private var listItems: [ListItem] = []
@State private var selectedJob: ListItem?
@State private var redraw: Int = 0
var body: some View {
VStack {
List(selection: $selectedJob) {
ForEach(self.listItems, id: \.id) { job in
self.itemRowView(for: job)
}
}
.id(redraw)
Button("Insert item at top") {
self.listItems.insert(
ListItem(
name: "List item \(listItems.count)"
),
at: 0
)
}
Button("Insert item at top with sub-item") {
self.listItems.insert(
ListItem(
name: "List item \(listItems.count)",
subjobs: [ListItem(name: "Sub-item")]
),
at: 0
)
}
Button("Append item") {
self.listItems.append(
ListItem(
name: "List item \(listItems.count)"
)
)
}
Button("Append item with sub-item") {
self.listItems.append(
ListItem(
name: "List item \(listItems.count)",
subjobs: [ListItem(name: "Sub-item")]
)
)
}
Button("Clear") {
self.listItems.removeAll()
}
Button("Redraw") {
self.redraw += 1
}
}
}
@ViewBuilder
private func itemRowView(for job: ListItem) -> some View {
if job.subItems == nil {
self.itemLabelView(for: job)
} else {
AnyView(
erasing: ListItemDisclosureGroup(job: job) {
self.itemLabelView(for: job)
} jobRowView: { child in
self.itemRowView(for: child)
}
)
}
}
@ViewBuilder private func itemLabelView(for job: ListItem) -> some View {
Text(job.name)
}
struct ListItemDisclosureGroup<LabelView: View, RowView: View>: View {
@ObservedObject var job: ListItem
@ViewBuilder let labelView: () -> LabelView
@ViewBuilder let jobRowView: (ListItem) -> RowView
var body: some View {
DisclosureGroup(isExpanded: $job.isExpanded) {
if let children = job.subItems {
ForEach(children, id: \.id) { child in
self.jobRowView(child)
}
}
} label: {
self.labelView()
}
}
}
}
SwiftUI List DisclosureGroup Rendering Issues on macOS 13 & 14
 
 
Q