I'm trying to learn SwiftUI by rewriting an old AppKit-based editor of mine. I'm currently stuck on something that is (fairly) straightforward using AppKit but seems almost impossible in SwiftUI (given my limited understanding of the latter).
What I'm trying to accomplish is a document-based app with tabbed views for the documents and a navigation sidebar to browse files (similar to e.g. Xcode).
The following is a minimal example of what I have come up with:
struct ContentView: View {
@Binding var document: FileBrowserTest4Document
let fileURL: URL?
var body: some View {
BrowserView(placeholder: fileURL?.absoluteString ?? "no file")
}
}
struct BrowserView: View {
let placeholder: String
@State private var root = FileItem(url: URL.documentsDirectory.appendingPathComponent("Test"))
var body: some View {
NavigationSplitView {
List([root], children: \.children) { item in
Button(action: { print("\(item.url)") }) {
Label(item.segment, systemImage: item.isFolder ? "folder" : "document")
.labelStyle(.titleAndIcon)
}
.buttonStyle(.plain)
}
HStack {
Button("Help") { print("Help") }
Button("Add…") { print("Add…") }
}
} detail: {
Text(placeholder)
}
}
}
where FileItem is basically a wrapper around URL not relevant to the question:
struct FileItem: Identifiable, Hashable {
let url: URL
...
}
The result is shown below (with the documents created by New and Open…, respectively.

- tabbed documents: check
- sidebar: check
- sidebar togggle button: check
However, the file tree in the browser is tied to the document instance and not "global" to the app. This is somewhat expected from the view hierarchy above, but not what I want. I've tried several approaches with e.g. HStack with NavigationStack + TextView, but no combination seem to achieve what I want. Searching the web turns up nothing helpful except solutions based on wrapping AppKit components. I feel like I'm in a a maze of twisty little passages, all alike…
Is what I want to do possible using SwiftUI? Any pointers, suggestions or definitive "No" would be greatly appreciated.
Update 251003:
Trying to clarify what I want to achieve (still exploring, not set in stone):
- double clicking a file in the navbar would open it (or bring to front an already open file) in a tab
- clicking
Add…button (bottom of navbar) would add a new file in the current directory (given by the selection in file tree) - Similarly, renaming/deleting files
- Add/Delete/Rename could be contextual menu
- Selecting a tab would highlight the corresponding entry in the file tree
- In practice, every document would have an associated
rootDirectorydetermining the root of the file tree
FWIW, I've been using TextMate for most of my editing for the past 20 years so I might be slightly one-eyed.
Update 251003-2:
Just pointing out that
NSDocumentController.shared.openDocument(
withContentsOf: item.url,
display: true,
completionHandler: {_,_,_ in print("Opened \(item.url)") }
)
as button action in the NavigationSplitView List would solve the first bullet above, but I guess that that counts as falling back to AppKit?
However, the file tree in the browser is tied to the document instance and not global to the app… but not what I want,that is not quite correct. What you have is simply how your data root is displayed in the view as a file tree. The data itself can be made global easily. What you don’t want is to make the view global—that’s not how SwiftUI works. That’s how AppKit works, which is totally different.