Provide views, controls, and layout structures for declaring your app's user interface using SwiftUI.

SwiftUI Documentation

Posts under SwiftUI subtopic

Post

Replies

Boosts

Views

Activity

Broken Constraints on macOS 26 SwiftUI App
I have a SwiftUI-lifecycle Mac app that uses a standard NavigationSplitView. When it runs on macOS 26 Beta 3, I see invalid constraint messages in the debugger at launch and when I navigate around the app's UI: Since this app is 100% SwiftUI, I'm not adding my own constraints. The invalid constraint is always the same. This has happened on every beta of macOS 26 and DOES NOT happen on macOS 14 or 15. I've filed feedback reports with no answer. Has anyone else encountered this with the betas?
Topic: UI Frameworks SubTopic: SwiftUI
1
0
97
Jul ’25
iOS 26 beta: Section headers no longer show translucent background when pinned with .listStyle(.plain)
Hi everyone, I've noticed a significant change in the visual behavior of List section headers between iOS 18 and iOS 26 beta that I'd like to clarify. Current Behavior: iOS 18 and earlier: Section headers with .listStyle(.plain) display with a translucent material background (regular material with blur effect) when pinned to the top during scrolling iOS 26 beta: Section headers with .listStyle(.plain) appear with a transparent/clear background even when pinned to the top Sample Code: struct ContentView: View { var body: some View { NavigationStack { List(1 ..< 5) { headerIndex in Section { ForEach(1...5, id: \.self) { rowIndex in HStack { Text("Row \(rowIndex)") .frame(height: 40) .padding(.horizontal) .background(Color.blue) Spacer() Image(systemName: "chevron.right") .foregroundStyle(.secondary) .font(.title3) } } } header: { Text("Header \(headerIndex)") .frame(height: 44) } .listRowSeparator(.hidden) } .listStyle(.plain) .clipped() } } } Questions: Is this change in header background behavior for .plain list style intentional in iOS 26? If so, what's the recommended way to maintain the previous material background appearance when headers are pinned? Should this be filed as feedback if it's unintended behavior? Testing Environment: Xcode 26.0 beta 3 (17A5276g) iOS 26 beta (23A5287g) vs iOS 18.5 Tested on simulator The translucent header background when pinned was quite useful for maintaining readability over scrolling content, so I'm hoping to understand if this is the new expected behavior or if there's a way to preserve the previous appearance. Any insights would be greatly appreciated! iOS 18.5 iOS 26 Beta
2
1
158
Jul ’25
List selection does not update model on MacOS. But same code works fine on iOS.
I have this code example that works perfectly on iOS. But on MacOS, the changes made in view presented by Navigation Stack gets reverted after I click on Back button. import SwiftUI import Observation enum Route: Hashable { case selection } let allSelectables: [String] = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"] @Observable class Model { var items: Set<String> = [] // Use Set for unique selections } struct ContentView: View { @State var model = Model() var body: some View { NavigationStack { VStack { Text("Selected: \(model.items.joined(separator: ", "))") List { NavigationLink(value: Route.selection) { Text("Go to Selection (\(model.items.count))") } } .navigationDestination(for: Route.self) { route in switch route { case .selection: List(allSelectables, id: \.self, selection: $model.items) { item in Text(item) } #if os(iOS) .environment(\.editMode, .constant(.active)) // Enable multiple selection #endif .navigationTitle("Selected: \(model.items.joined(separator: ", "))") } } } } } }
Topic: UI Frameworks SubTopic: SwiftUI
1
0
95
Jul ’25
Multi-Selection List : changing Binding Array to Binding Set and back again
I am trying to create a menu picker for two or three text items. Small miracles, but I have it basically working. Problem is it uses a set, and I want to pass arrays. I need to modify PickerView so the Bound Parameter is an [String] instead of Set. Have been fighting this for a while now... Hoping for insights. struct PickerView: View { @Binding var colorChoices: Set<String> let defaults = UserDefaults.standard var body: some View { let possibleColors = defaults.object(forKey: "ColorChoices") as? [String] ?? [String]() Menu { ForEach(possibleColors, id: \.self) { item in Button(action: { if colorChoices.contains(item) { colorChoices.remove(item) } else { colorChoices.insert(item) } }) { HStack { Text(item) Spacer() if colorChoices.contains(item) { Image(systemName: "checkmark") } } } } } label: { Label("Select Items", systemImage: "ellipsis.circle") } Text("Selected Colors: \(colorChoices, format: .list(type: .and))") } } #Preview("empty") { @Previewable @State var colorChoices: Set<String> = [] PickerView(colorChoices: $colorChoices) } #Preview("Prefilled") { @Previewable @State var colorChoices: Set<String> = ["Red","Blue"] PickerView(colorChoices: $colorChoices) } My Content View is suppose to set default values the first time it runs, if no values already exist... import SwiftUI struct ContentView: View { @State private var viewDidLoad: Bool = false var body: some View { HomeView() .onAppear { // The following code should execute once the first time contentview loads. If a user navigates back to it, it should not execute a second time. if viewDidLoad == false { viewDidLoad = true // load user defaults let defaults = UserDefaults.standard // set the default list of school colors, unless the user has already updated it prior let defaultColorChoices: [String] = ["Black","Gold","Blue","Red","Green","White"] let colorChoices = defaults.object(forKey: "ColorChoices") as? [String] ?? defaultColorChoices defaults.set(colorChoices, forKey: "ColorChoices") } } } } #Preview { ContentView() } PickLoader allows you to dynamically add or delete choices from the list... import SwiftUI struct PickLoader: View { @State private var newColor: String = "" var body: some View { Form { Section("Active Color Choices") { // we should have set a default color list in contentview, so empty string should not be possible. let defaults = UserDefaults.standard let colorChoices = defaults.object(forKey: "ColorChoices") as? [String] ?? [String]() List { ForEach(colorChoices, id: \.self) { color in Text(color) } .onDelete(perform: delete) HStack { TextField("Add a color", text: $newColor) Button("Add"){ defaults.set(colorChoices + [newColor], forKey: "ColorChoices") newColor = "" } } } } } .navigationTitle("Load Picker") Button("Reset Default Choices") { let defaults = UserDefaults.standard //UserDefaults.standard.removeObject(forKey: "ColorChoices") let colorChoices: [String] = ["Black","Gold","Blue","Red","Green","White"] defaults.set(colorChoices, forKey: "ColorChoices") } Button("Clear all choices") { let defaults = UserDefaults.standard defaults.removeObject(forKey: "ColorChoices") } } } func delete(at offsets: IndexSet) { let defaults = UserDefaults.standard var colorChoices = defaults.object(forKey: "ColorChoices") as? [String] ?? [String]() colorChoices.remove(atOffsets: offsets) defaults.set(colorChoices, forKey: "ColorChoices") } #Preview { PickLoader() } And finally HomeView is where I am testing from - to see if binding works properly... import SwiftUI struct HomeView: View { //@State private var selection: Set<String> = [] //@State private var selection: Set<String> = ["Blue"] @State private var selection: Set<String> = ["Blue", "Red"] var body: some View { NavigationStack { List { Section("Edit Picker") { NavigationLink("Load Picker") { PickLoader() } } Section("Test Picker") { PickerView(colorChoices: $selection) } Section("Current Results") { Text("Current Selection: \(selection, format: .list(type: .and))") } } .navigationBarTitle("Hello, World!") } } } #Preview { HomeView() } If anyone uses this code, there are still issues - buttons on Loader don't update the list on the screen for one, and also dealing with deleting choices that are in use - how does picker deal with them? Probably simply add to the list automatically and move on. If anyone has insights on any of this also, great! but first I just need to understand how to accept an array instead of a set in pickerView. I have tried using a computed value with a get and set, but I can't seem to get it right. Thanks for any assistance! Cheers!
2
0
159
Jul ’25
"The compiler is unable to type-check this expression..."
"/Users/rich/Work/IdeaBlitz/IdeaBlitz/IdeaListView.swift:30:25 The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions" Is it just me? I get this on syntax errors, missing commas, missing quotes, and for no particular reason at all that I can see. I don't think I've been able to write a single, simple, SwiftUI view without seeing this multiple times. "Breaking it up" just makes it harder to read. Simple, inline, 2-page views become 8-page, totally unreadable, monstrosities. Am I doing something wrong? Or is this just the state of SwiftUI today? Or is there some way to tell the compiler to take more time on this expression? I mean, if these can be broken up automatically, then why doesn't the compiler to that already?
2
0
164
Jul ’25
Logo flying from the corner
Whenever I load a resized image into a 70 by 70 frame, when I run the loading screen on the simulator, it looks like the image is flying from the top left corner of the screen on load, however, when I load it in the previews, it starts where its supposed to be in the center. Both are scaled properly, however, the first ones position is acting like I put a transition on it when I did not import SwiftUI struct LoadingView: View { @Environment(\.colorScheme) private var colorScheme var text: String? = nil @State private var isSpinning = false var body: some View { VStack{ Image("Jeromes_Logo") .resizable() .frame(width: 70, height: 70) .rotationEffect(.degrees(isSpinning ? 360 : 0)) .animation( .bouncy(duration: 0.4, extraBounce: 0.2) .repeatForever(autoreverses: false), value: isSpinning ) .onAppear { isSpinning = true } if let text = text { Text(text) } } .frame(maxWidth: .infinity, maxHeight: .infinity) } } #Preview { LoadingView(text: "loading") }
2
0
446
Jul ’25
iOS 26 Beta 3 ScrollPosition object not executing scroll commands while scrollPosition(id:) binding works
I'm implementing a horizontal carousel in iOS 26 Beta 3 using SwiftUI ScrollView with LazyHStack. The goal is to programmatically scroll to a specific card on view load. What I'm trying to do: Display a horizontal carousel of cards using ScrollView + LazyHStack Automatically scroll to the "current" card when the view appears Use iOS 26's new ScrollPosition object for programmatic scrolling Current behavior: The ScrollPosition object receives scroll commands (confirmed via console logs) The scrollTo(id:anchor:) method executes without errors However, the ScrollView does not actually scroll - it remains at position 0 Manual scrolling and scrollTargetBehavior(.viewAligned) work perfectly Code snippet: @State private var scrollPositionObject = ScrollPosition() ScrollView(.horizontal) { LazyHStack(spacing: 16) { ForEach(cards, id: .id) { card in CardView(card: card) .id(card.id) } } .scrollTargetLayout() } .scrollPosition($scrollPositionObject) .scrollTargetBehavior(.viewAligned) .onAppear { let targetId = cards[currentIndex].id DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { scrollPositionObject.scrollTo(id: targetId, anchor: .center) } } Workaround that works: Using the iOS 17 scrollPosition(id:) binding instead of the ScrollPosition object: @State private var scrollPosition: UUID? .scrollPosition(id: $scrollPosition) .onAppear { scrollPosition = cards[currentIndex].id } Environment: iOS 26 Beta 3 Xcode 26 Beta 3 Physical device (iPhone 16 Pro Max) Is this a known issue with ScrollPosition in Beta 3, or am I missing something in the implementation? The older binding approach works fine, but I'd prefer to use the new ScrollPosition API if possible.
Topic: UI Frameworks SubTopic: SwiftUI
0
1
87
Jul ’25
SwiftData and discarding unsaved changes idea???
Someone smarter than me please tell me if this will work... I want to have an edit screen for a SwiftData class. Auto Save is on, but I want to be able to revert changes. I have read all about sending a copy in, sending an ID and creating a new context without autosave, etc. What about simply creating a second set of ephemeral values in the actual original model. initialize them with the actual fields. Edit them and if you save changes, migrate that back to the permanent fields before returning. Don't have to manage a list of @State variables corresponding to every model field, and don't have to worry about a second model context. Anyone have any idea of the memory / performance implications of doing it this way, and if it is even possible? Does this just make a not quite simple situation even more complicated? Haven't tried yet, just got inspiration from reading some medium content on attributes on my lunch break, and wondering if I am just silly for considering it.
2
0
156
Jul ’25
Sheet-like presentation on the side on iPad
Is there a way to get a sheet on the side over an interactive view with a proper glass background on iPad? Ideally, including being able to drag the sheet between medium/large-height sizes (like a sheet with presentationDetents on iPhone), similar to the Maps app: I tried the NavigationSplitView like in the NavigationCookbook example. This is somewhat like it, but it's too narrow (sidebar-like) and doesn't get the full navigation bar: I also played around with .sheet and .presentationDetents and the related modifiers, thinking I could make the sheet appear to the side; but no luck here. It seems to have all the correct behaviors, but it's always presented form-like in the center: Example code for the sheet: import SwiftUI import MapKit struct ContentView: View { var body: some View { Map() .sheet(isPresented: .constant(true)) { NavigationStack { VStack { Text("Hello") NavigationLink("Show Foo") { Text("Foo") .navigationTitle("Foo") .containerBackground(Color.clear, for: .navigation) } } } .presentationDetents([.medium, .large]) .presentationBackgroundInteraction(.enabled) } } } I also tried placing the NavigationStack as an overlay and putting a .glassEffect behind it. From the first sight, this looks okay-ish on beta 3, but seems prone to tricky gotchas and edge cases around the glass effects and related transitions. Seems like not a good approach to me, building such navigational containers myself has been a way too big time-sink for me in the past... Anyway, example code for the overlay approach: import SwiftUI import MapKit struct ContentView: View { var body: some View { Map() .overlay(alignment: .topLeading) { NavigationStack { VStack { Text("Hello") NavigationLink("Show Foo") { ScrollView { VStack { ForEach(1...30, id: \.self) { no in Button("Hello world") {} .buttonStyle(.bordered) } } .frame(maxWidth: .infinity) } .navigationTitle("Foo") .containerBackground(Color.clear, for: .navigation) } } .containerBackground(Color.clear, for: .navigation) } .frame(width: 400) .frame(height: 600) .glassEffect(.regular, in: .rect(cornerRadius: 22)) .padding() } } } Do I miss something here or is this not possible currently with built-in means of the SwiftUI API?
Topic: UI Frameworks SubTopic: SwiftUI
3
2
276
Jul ’25
Does the canvas view on top of the PDFView not re-render?
I added a canvas view using PDFPageOverlayViewProvider. When I zoom the PDFView, the drawing is scaled, but its quality becomes blurry. How can I fix this? import SwiftUI import PDFKit import PencilKit import CoreGraphics struct ContentView: View { var body: some View { if let url = Bundle.main.url(forResource: "sample", withExtension: "pdf"), let data = try? Data(contentsOf: url), let document = PDFDocument(data: data) { PDFRepresentableView(document: document) } else { Text("fail") } } } #Preview { ContentView() } struct PDFRepresentableView: UIViewRepresentable { let document: PDFDocument let pdfView = PDFView() func makeUIView(context: Context) -> PDFView { pdfView.displayMode = .singlePageContinuous pdfView.usePageViewController(false) pdfView.displayDirection = .vertical pdfView.pageOverlayViewProvider = context.coordinator pdfView.document = document pdfView.autoScales = false pdfView.minScaleFactor = 0.7 pdfView.maxScaleFactor = 4 return pdfView } func updateUIView(_ uiView: PDFView, context: Context) { // Optional: update logic if needed } func makeCoordinator() -> CustomCoordinator { return CustomCoordinator(parent: self) } } class CustomCoordinator: NSObject, PDFPageOverlayViewProvider, PKCanvasViewDelegate { let parent: PDFRepresentableView init(parent: PDFRepresentableView) { self.parent = parent } func pdfView(_ view: PDFView, overlayViewFor page: PDFPage) -> UIView? { let result = UIView() let canvasView = PKCanvasView() canvasView.drawingPolicy = .anyInput canvasView.tool = PKInkingTool(.pen, color: .blue, width: 20) canvasView.translatesAutoresizingMaskIntoConstraints = false result.addSubview(canvasView) NSLayoutConstraint.activate([ canvasView.leadingAnchor.constraint(equalTo: result.leadingAnchor), canvasView.trailingAnchor.constraint(equalTo: result.trailingAnchor), canvasView.topAnchor.constraint(equalTo: result.topAnchor), canvasView.bottomAnchor.constraint(equalTo: result.bottomAnchor) ]) for subView in view.documentView?.subviews ?? [] { subView.isUserInteractionEnabled = true } result.layoutIfNeeded() return result } }
1
0
172
Jul ’25
Section Does Not Seem To Expand/Collapse
This is obviously a user error, but I've been working on different possibilities for a couple of days and nothing works. The problem is my Section in the following code doesn't expand or collapse when I click on the chevron: `class AstroCat { var title: String var contents: [ String ] var isExpanded: Bool init(title: String, contents: [String], isExpanded: Bool) { self.title = title self.contents = contents self.isExpanded = isExpanded } } struct TestView: View { @Binding var isShowingTargetSelection: Bool @State var catalog: AstroCat @State private var expanded = false var body: some View { NavigationStack { List { Section(catalog.title, isExpanded: $catalog.isExpanded) { ForEach(catalog.contents, id: \.self) { object in Text(object) } } } .navigationTitle("Target") .listStyle(.sidebar) } } } #Preview { struct TestPreviewContainer : View { @State private var value = false @State var catalog = AstroCat(title: "Solar System", contents: ["Sun", "Mercury", "Venus", "Earth"], isExpanded: true) var body: some View { TestView(isShowingTargetSelection: $value, catalog: catalog) } } return TestPreviewContainer() }` If I change the "isExpanded: $catalog.isExpanded" to just use the local variable "expanded", then it works, so I think I have the basic SwiftUI pieces correct. But using a boolean inside of the class doesn't seem to work (the section just remains expanded or collapsed based on the initial value of the class variable). Any hints? Am I not specifying the binding correctly? (I've tried a bunch of alternatives) Thanks for the help, Robert
2
0
120
Jul ’25
View lifecycle in Tabview
In TabView, when I open a view in a Tab, and I switch to another Tab, but the View lifecycle of the view in the old Tab is still not over, and the threads of some functions are still in the background. I want to completely end the View lifecycle of the View in the previously opened tab when switching Tab. How can I do it? Thank you!
0
0
124
Jul ’25
Observation feedback loop on simple Map() view declaration
Project minimum iOS deployment is set to 16.4. When running this simple code in console we receive "Observation tracking feedback loop detected!" and map is unusable. Run code: Map(coordinateRegion: .constant(.init())) Console report: ... Observable object key path '\_UICornerProvider.<computed 0x00000001a2768bc0 (Optional<UICoordinateSpace>)>' changed; performing invalidation for [layout] of: <_TtGC7SwiftUI21UIKitPlatformViewHostGVS_P10$1a57c8f9c32PlatformViewRepresentableAdaptorGV15_MapKit_SwiftUI8_MapViewGSaVS2_P10$24ce3fc8014AnnotationData____: 0x10acc2d00; baseClass = _TtGC5UIKit22UICorePlatformViewHostGV7SwiftUIP10$1a57c8f9c32PlatformViewRepresentableAdaptorGV15_MapKit_SwiftUI8_MapViewGSaVS3_P10$24ce3fc8014AnnotationData____; frame = (0 0; 353 595); anchorPoint = (0, 0); tintColor = UIExtendedSRGBColorSpace 0.333333 0.333333 0.333333 1; layer = <CALayer: 0x12443a430>> Observable object key path '\_UICornerProvider.<computed 0x00000001a2768bc0 (Optional<UICoordinateSpace>)>' changed; performing invalidation for [layout] of: <_MapKit_SwiftUI._SwiftUIMKMapView: 0x10ae8ce00; frame = (0 0; 353 595); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x113beb7e0>> Observable object key path '\_UICornerProvider.<computed 0x00000001a2768bc0 (Optional<UICoordinateSpace>)>' changed; performing invalidation for [layout] of: <_MapKit_SwiftUI._SwiftUIMKMapView: 0x10ae8ce00; frame = (0 0; 353 595); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x113beb7e0>> Observable object key path '\_UICornerProvider.<computed 0x00000001a2768bc0 (Optional<UICoordinateSpace>)>' changed; performing invalidation for [layout] of: <_MapKit_SwiftUI._SwiftUIMKMapView: 0x10ae8ce00; frame = (0 0; 353 595); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x113beb7e0>> Observation tracking feedback loop detected! Make a symbolic breakpoint at UIObservationTrackingFeedbackLoopDetected to catch this in the debugger. Refer to the console logs for details about recent invalidations; you can also make a symbolic breakpoint at UIObservationTrackingInvalidated to catch invalidations in the debugger. Object receiving repeated [layout] invalidations: <_TtGC7SwiftUI21UIKitPlatformViewHostGVS_P10$1a57c8f9c32PlatformViewRepresentableAdaptorGV15_MapKit_SwiftUI8_MapViewGSaVS2_P10$24ce3fc8014AnnotationData____: 0x10acc2d00; baseClass = _TtGC5UIKit22UICorePlatformViewHostGV7SwiftUIP10$1a57c8f9c32PlatformViewRepresentableAdaptorGV15_MapKit_SwiftUI8_MapViewGSaVS3_P10$24ce3fc8014AnnotationData____; frame = (0 0; 353 595); anchorPoint = (0, 0); tintColor = UIExtendedSRGBColorSpace 0.333333 0.333333 0.333333 1; layer = <CALayer: 0x12443a430>> Observation tracking feedback loop detected! Make a symbolic breakpoint at UIObservationTrackingFeedbackLoopDetected to catch this in the debugger. Refer to the console logs for details about recent invalidations; you can also make a symbolic breakpoint at UIObservationTrackingInvalidated to catch invalidations in the debugger. Object receiving repeated [layout] invalidations: <_MapKit_SwiftUI._SwiftUIMKMapView: 0x10ae8ce00; frame = (0 0; 353 595); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x113beb7e0>> IDE: Xcode 26 Beta 3 Testing device: iPhone 15 Pro iOS 26 Beta 3 MacOS: Tahoe 26 Beta 3
2
3
132
Jul ’25
Implicit list row animations broken in Form container on iOS 26 beta 3
[Submitted as FB18870294, but posting here for visibility.] In iOS 26 beta 3 (23A5287g), implicit animations no longer work when conditionally showing or hiding rows in a Form. Rows with Text or other views inside a Section appear and disappear abruptly, even when wrapped in withAnimation or using .animation() modifiers. This is a regression from iOS 18.5, where the row item animates in and out correctly with the same code. Repro Steps Create a new iOS App › SwiftUI project. Replace its ContentView struct with the code below Build and run on an iOS 18 device. Tap the Show Middle Row toggle and note how the Middle Row animates. Build and run on an iOS 26 beta 3 device. Tap the Show Middle Row toggle. Expected Middle Row item should smoothly animate in and out as it does on iOS 18. Actual Middle Row item appears and disappears abruptly, without any animation. Code struct ContentView: View { @State private var showingMiddleRow = false var body: some View { Form { Section { Toggle( "Show **Middle Row**", isOn: $showingMiddleRow.animation() ) if showingMiddleRow { Text("Middle Row") } Text("Last Row") } } } }
3
3
174
Jul ’25
Disable Hit Testing on SwiftUI Map Annotation Content
Hi, I’m using SwiftUI’s Map with custom Annotation content and trying to make the annotation view ignore touch interactions—similar to applying .allowsHitTesting(false) on regular views. The goal is to ensure that map gestures such as long press and drag are not blocked by annotation content. However, setting .allowsHitTesting(false) on the annotation content doesn’t seem to have any effect. Is there any workaround or supported approach to allow the map to receive gestures even when they originate from annotation views? Thanks in advance for any guidance!
0
0
69
Jul ’25
How to use protocols to support managing SwiftUI views from different modules ?
In out project, we are creating a modular architecture where each module conform to certain protocol requirements for displaying the UI. For example: public protocol ModuleProviding: Sendable { associatedtype Content: View /// Creates and returns the main entry point view for this module /// - Parameter completion: Optional closure to be called when the flow completes /// - Returns: The main view for this module @MainActor func createView(_ completion: (() -> Void)?) -> Content } This protocol can be implemented by all different modules in the app, and I use a ViewProvider structure to build the UI from the module provided: public struct ViewProvider: Equatable { let id = UUID() let provider: any ModuleProviding let completion: () -> Void public init(provider: any ModuleProviding, completion: @escaping () -> Void) { self.provider = provider self.completion = completion } @MainActor public func layoutUI() -> some View { provider.createView(completion) } This code throws an error: Type 'any View' cannot conform to 'View' To solve this error, there are two ways, one is to wrap it in AnyView, which I don't want to do. The other option is to type check the provider with its concrete type: @ViewBuilder @MainActor private func buildViewForProvider(_ provider: any ModuleProviding, completion: (() -> Void)?) -> some View { switch provider { case let p as LoginProvider: p.createView(completion) case let p as PostAuthViewProvider: p.createView(completion) case let p as OnboardingProvider: p.createView(completion) case let p as RewardsProvider: p.createView(completion) case let p as SplashScreenProvider: p.createView(completion) default: EmptyView() } } This approach worked, but it defeats the purpose of using protocols and it is not scalable anymore. Are there any other approaches I can look at ? Or is this limitation in SwiftUI ?
3
0
113
Jul ’25
Using NSHostingSceneRepresentation to open arbitrary window in AppKit app
I’m trying to open a window from a SwiftUI Scene inside an AppKit app using NSHostingSceneRepresentation (macOS 26). The idea is that I want to call openWindow(id: "some-id") to show the new window. However, nothing happens when I try this — no window appears, and there’s nothing in the logs. Interestingly, if I use the openSettings() route instead, it does open a window. Does anyone know the correct way to open an arbitrary SwiftUI window scene from an AppKit app? import Cocoa import SwiftUI @main class AppDelegate: NSObject, NSApplicationDelegate { let settingsScene = NSHostingSceneRepresentation { #if true MyWindowScene() #else Settings { Text("My Settings") } #endif } func applicationWillFinishLaunching(_ notification: Notification) { NSApplication.shared.addSceneRepresentation(settingsScene) } @IBAction func showAppSettings(_ sender: NSMenuItem) { #if true settingsScene.environment.openWindow(id: MyWindowScene.windowID) #else settingsScene.environment.openSettings() #endif } } struct MyWindowScene: Scene { static let windowID = "com.company.MySampleApp.myWindow" var body: some Scene { Window("Sample Window", id: MyWindowScene.windowID) { Text("Sample Content") .scenePadding() } } }
Topic: UI Frameworks SubTopic: SwiftUI
0
0
74
Jul ’25