I am using an NSOutlineView via NSViewRepresentable in a SwiftUI application running on macOS. Everything has been working fine.
Up until lately, I've been returning a custom NSView for each item using the standard:
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
// View recycling omitted.
return MyItemView(item)
}
Now I want to explore using a little bit more SwiftUI and returning an NSHostingView from this delegate method.
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
// View recycling omitted.
let rootView = MySwiftUIView(item)
let hostingView = NSHostingView(rootView: rootView)
return hostingView
}
For the most part, this appears to be working fine. NSOutlineView is even correctly applying highlight styling, so that's great.
But there's one small glitch. The outline view's disclosure triangles do not align with the hosting view's content. The disclosure triangles appear to just be pinned to the top. Perhaps they can't find a baseline constraint or something?
Is there any SwiftUI modifier or AppKit/SwiftUI technique I can apply here to get the disclosure button to appear in the right place?
Here is what the SwiftUI + NSHostingView version looks
like:
Note the offset disclosure indicators. (Image spacing is a bit off as well using Label, but fixable.
Here is what an NSView with NSTextFields looks like:
Disclosure indicators are correctly aligned, as you would expect.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
NSVisualEffectView in AppKit has two main properties: material and blendingMode.
Material is well supported in SwiftUI, but I can't seem to find an equivalent for blendingMode.
What is the SwiftUI equivalent to NSVisualEffect.BlendingMode?
I'm looking for clarification on a SwiftUI performance point mentioned in the recent Optimize your app's speed and efficiency | Meet with Apple video.
(YouTube link not allowed, but the video is available on the Apple Developer channel.)
At the 1:48:50 mark, the presenter says:
Writing a value to the Environment doesn't only affect the views that read the key you're updating. It updates any view that reads from any Environment key. [abbreviated quote]
That statement seems like a big deal if your app relies heavily on Environment values.
Context
I'm building a macOS application with a traditional three-panel layout. At any given time, there are many views on screen, plus others that exist in the hierarchy but are currently hidden (for example, views inside tab views or collapsed splitters).
Nearly every major view reads something from the environment—often an @Observable object that acts as a service or provider.
However, there are a few relatively small values that are written to the environment frequently, such as:
The selected tab index
The currently selected object on a canvas
The Question
Based on the presenter's statement, I’m wondering:
Does writing any value to the environment really cause all views in the entire SwiftUI view hierarchy that read any environment key to have their body re-evaluated?
Do environment writes only affect child views, or do they propagate through the entire SwiftUI hierarchy?
Example:
View A
└─ View B
├─ View C
└─ View D
If View B updates an environment value, does that affect only C and D, or does it also trigger updates in A and B (assuming each view has at least one @Environment property)?
Possible Alternative
If all views are indeed invalidated by environment writes, would it be more efficient to “wrap” frequently-changing values inside an @Observable object instead of updating the environment directly?
// Pseudocode
@Observable final class SelectedTab {
var index: Int
}
ContentView()
.environment(\.selectedTab, selectedTab)
struct TabView: View {
@Environment(\.selectedTab) private var selectedTab
var body: some View {
Button("Action") {
// Would this avoid invalidating all views using the environment?
selectedTab.index = 1
}
}
}
Summary
From what I understand, it sounds like the environment should primarily be used for stable, long-lived objects—not for rapidly changing values—since writes might cause far more view invalidations than most developers realize.
Is that an accurate interpretation?
Follow-Up
In Xcode 26 / Instruments, is there a way to monitor writes to @Environment?