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

Posts under SwiftUI tag

200 Posts

Post

Replies

Boosts

Views

Activity

NavigationSplitView: Make button clickable in detail-section safe area
Hi, I've tried to find a solution for this problem for weeks now but it seems no one knows how to solve it and Apple doesn't seem to care. I have a NavigationSplitView with two columns. In the detail column I have a button - or any other clickable control - which is placed in the very top where usually the safe area resides. The button is NOT clickable when he is in the safe area and I have NO idea why. I know I can place buttons in safe areas of other views and they are clickable. Please have a look at the code: `struct NavTestView: View { var body: some View { GeometryReader { p in VStack(spacing: 0) { NavigationSplitView { List(names) { Text($0.name).frame(width: p.size.width) .background(Color.green) }.listRowSpacing(p.size.height * 0.15 / 100 ) .toolbar(.hidden, for: .navigationBar) } detail: { TestView().ignoresSafeArea() }.frame(width: p.size.width, height: p.size.height, alignment: .topLeading) .background(Color.yellow) } } } } struct TestView: View { var body: some View { GeometryReader { p in let plusButton = IconButton(imageName: "plus.circle.fill", color: Color(uiColor: ThemeColor.SeaFoam.color), imageWidth: p.size.width * 5 / 100, buttonWidth: p.size.width * 5 / 100) let regularAddButton = Button(action: { log.info("| Regular Add Button pressed") } ) { plusButton } VStack { regularAddButton }.frame(width: p.size.width , height: p.size.height, alignment: .top) .background(Color.yellow) } } } ` this code produces the following screen: Any help would be really greatly appreciated! Thank you! Frank
1
0
654
1w
SwiftUI buttons behind NSToolbarView are not clickable on macOS 26 beta
Overview Starting with macOS 26 beta 1, a new NSGlassContainerView is added inside NSToolbarView. This view intercepts mouse events, so any SwiftUI Button (or other interactive view) overlaid on the title‑bar / toolbar area no longer receives clicks. (The same code works fine on macOS 15 and earlier.) Filed as FB18201935 via Feedback Assistant. Reproduction (minimal project) macOS 15 or earlier → button is clickable macOS 26 beta → button cannot be clicked (no highlight, no action call) @main struct Test_macOS26App: App { init() { // Uncomment to work around the issue (see next section) // enableToolbarClickThrough() } var body: some Scene { WindowGroup { ContentView() } .windowStyle(.hiddenTitleBar) // ⭐️ hide the title bar } } struct ContentView: View { var body: some View { NavigationSplitView { List { Text("sidebar") } } detail: { HSplitView { listWithOverlay listWithOverlay } } } private var listWithOverlay: some View { List(0..<30) { Text("item: \($0)") } .overlay(alignment: .topTrailing) { // ⭐️ overlay in the toolbar area Button("test") { print("test") } .glassEffect() .ignoresSafeArea() } } } Investigation In Xcode View Hierarchy Debugger, a layer chain NSToolbarView > NSGlassContainerView sits in front of the button. -[NSView hitTest:] on NSGlassContainerView returns itself, so the event never reaches the SwiftUI layer. Swizzling hitTest: to return nil when the result is the view itself makes the click go through: func enableToolbarClickThrough() { guard let cls = NSClassFromString("NSGlassContainerView"), let m = class_getInstanceMethod(cls, #selector(NSView.hitTest(_:))) else { return } typealias Fn = @convention(c)(AnyObject, Selector, NSPoint) -> Unmanaged<NSView>? let origIMP = unsafeBitCast(method_getImplementation(m), to: Fn.self) let block: @convention(block)(AnyObject, NSPoint) -> NSView? = { obj, pt in guard let v = origIMP(obj, #selector(NSView.hitTest(_:)), pt)?.takeUnretainedValue() else { return nil } return v === (obj as AnyObject) ? nil : v // ★ make the container transparent } method_setImplementation(m, imp_implementationWithBlock(block)) } Questions / Call for Feedback Is this an intentional behavioral change? If so, what is the recommended public API or pattern for allowing clicks to reach views overlaid behind the toolbar? Any additional data points or confirmations are welcome—please reply if you can reproduce the issue or know of an official workaround. Thanks in advance!
3
0
218
1w
NavigationSplitView detail view with safearea
Hi, I have a NavigationSplitView with a view in the detail section: NavigationSplitView { ZStack { Color.black.ignoresSafeArea() gradientBlack2Blue.opacity(0.25) .ignoresSafeArea() GeometryReader { p in VStack { List { SidebarViewCell(id: "1", text: "Steuersätze" , type: .TAX_MASTERDATA , selectedMasterdataType: $selectedMasterdataType) }.listRowSpacing(size.height * 1.25 / 100 ) .scrollContentBackground(.hidden) .toolbar(.hidden, for: .navigationBar) .frame(width: p.size.width * 98 / 100 , height: p.size.height, alignment: .topLeading). }alignment: .topLeading) } } } detail: { MasterdataDetailView().ignoresSafeArea() } }.navigationSplitViewStyle(.balanced) When I place a Button-Control in the MasterdataDetailView it cannot be clicked because it is in the safe area. How can I make it clickable? Best Regards, Frank
8
0
1.6k
1w
Correct way to handle 2 to 3 column switch
I'm using a NavigationSplitView on macOS which needs to show 2 or 3 columns depending on the selection of the sidebar. Column 1 has a list of main activities. Some of these just have some data to show and some have a sublist. Currently, when an item that has no sublist is selected, I set the 2nd column (content:) to: Spacer() .navigationSplitViewColumnWidth(0) This works, although it started hitting bugs requiring a workaround on macOS 26, which got me wondering, what is the correct approach here? NavigationSplitViewVisibility.doubleColumn is not the solution, as this hides column 1, not column 2.
Topic: Design SubTopic: General Tags:
0
0
745
1w
Simply including "@Environment(\.dismiss) ..." causes multiple calls to a view's body
When I run the code below, the trace, "Called", is shown 3-4 times initially. If I click on a color row, the trace shows 9 times. Why is that? If I comment out the line, @Environment(\.dismiss) private var dismiss, the trace shows only 1 time, as expected. I've read a number of reports regarding dismiss() which seems to be very brittle. It often causes an infinite loop. But I need to dismiss a view. Its older counterpart, @Environment(\.presentationMode), seems to cause infinite loop at times. Are there other ways to dismiss a view without suffering these issues? struct TestNavigationLink: View { @Environment(\.dismiss) private var dismiss var body: some View { let _ = print("Called") NavigationStack { List { NavigationLink("Mint") { ColorDetail(color: .mint) } } .navigationTitle("Colors") } } // body struct ColorDetail: View { var color: Color var body: some View { color.navigationTitle(color.description) } } }
2
1
662
1w
I found a liquid glass bug
When I use rotation3DEffect to rorate a UI element with liquid glass, the liquid glass turns black and expands struct TestCardView: View { @State var rotation:CGFloat = 0.0 @State var vertical: Double = 0 @State var horizontal: Double = 0 var body: some View { ZStack { Image("paintImage") .resizable() .scaledToFill() .ignoresSafeArea() .blur(radius: 10) // Card container ZStack { // Add content here Image("paintImage") .resizable() .clipShape(RoundedRectangle(cornerRadius: 20)) .padding(10) VStack { Spacer() Text("Placeholder text Placeholder text Placeholder text Placeholder text ") .multilineTextAlignment(.center) .padding(12) .glassEffect(.clear, in: RoundedRectangle(cornerRadius: 12, style: .continuous)) .shadow(color: .black.opacity(0.2), radius: 8, x: 0, y: 4) .padding(.bottom, 8) } .padding(25) } .frame(width: 360, height: 600) .clipShape(RoundedRectangle(cornerRadius: 20)) .glassEffect(.clear, in: RoundedRectangle(cornerRadius: 20)) .rotation3DEffect(.degrees(vertical),axis: (x: 1, y: 0, z: 0)) .rotation3DEffect(.degrees(horizontal),axis: (x: 0, y: 1, z: 0)) .gesture( DragGesture(minimumDistance: 0) .onChanged { value in withAnimation{ vertical = min(max(Double(value.translation.height / 10), -20), 20) horizontal = min(max(Double(value.translation.width / 10), -15), 15) } } .onEnded { _ in withAnimation(.easeOut(duration: 0.5)) { vertical = 0 horizontal = 0 } } ) } } }
2
0
68
1w
NavigationPath.append but .navigationDestination Not Being Called
I am trying to do a bit of fancy navigation in SwiftUI using NavigationPath and am having a problem. I have a root view with includes a button: struct ClassListScreen: View { @Bindable private var router = AppRouter.shared @State private var addCourse: Bool = false ... var body: some View { ... Button("Add Class") { router.currentPath.append(addCourse) }.buttonStyle(.borderedProminent) ... .navigationDestination(for: Bool.self){ _ in ClassAddDialog { course in sortCourses() } } } } router.currentPath is the NavigationPath associated with the operative NavigationStack. (This app has a TabView and each Tab has its own NavigationStack and NavigationPath). Tapping the button correctly opens the ClassAddDialog. In ClassAddDialog is another button: struct ClassAddDialog: View { @Bindable private var router = AppRouter.shared @State private var idString: String = "" ... var body: some View { ... Button("Save") { let course = ... ... (save logic) idString = course.id.uuidString var path = router.currentPath path.removeLast() path.append(idString) router.currentPath = path }.buttonStyle(.borderedProminent) ... .navigationDestination(for: String.self) { str in if let id = UUID(uuidString: str), let course = Course.findByID(id, with: context) { ClassDetailScreen(course: course) } } } } My intent here is that tapping the Save button in ClassAddDialog would pop that view and move directly to the ClassDetailScreen (without returning to the root ClassListScreen). The problem is that the code inside the navigationDestination is NEVER hit. (I.e., a breakpoint on the if let ... statement) never fires. I just end up on a (nearly) blank view with a warning triangle icon in its center. (And yes, the back button takes me to the root, so the ClassAddDialog WAS removed as expected.) And I don't understand why. Can anyone share any insight here?
0
0
31
1w
Is ContactAccessButton broken?
Simple question - on iOS 26 ContactAccessButton does not appear to show any UI when attempting to search for a contact in either the contact access picker on the ContactAccessButton. This behavior occurs in the Apple provided sample code , as well as a basic example: struct ContentView: View { @State var searchText : String = "" var body: some View { VStack { TextField("Search", text: $searchText) ContactAccessButton( queryString: searchText, ignoredEmails: nil, ignoredPhoneNumbers: nil, approvalCallback: { identifiers in print(identifiers) }) } .padding() } } Am I doing something wrong or is this just not working?
1
0
50
1w
Scroll TextEditor to cursor position
Hello. Is there a good SwiftUI approach on getting the TextEditor cursor position? I have a TextEditor and sometimes when we have a longer text inside it, the cursor is not seen because the keyboard is above covering the bottom of the TextEditor. I would like to somehow detect the position of the cursor, and if it's on the last line of the TextEditor, scroll to the bottom. I've already checked a bit and didn't find any good method of doing this in SwiftUI. If you have any ideas on how to do this, or even a different method any help would be highly appreciated. Thank you!
1
2
787
1w
"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?
3
0
224
1w
Combining NavigationSplitView and TabView in iOS 18
Hi folks, I've used a NavigationSplitView within one of the tabs of my app since iOS 16, but with the new styling in iOS 18 the toolbar region looks odd. In other tabs using e.g. simple stacks, the toolbar buttons are horizontally in line with the new tab picker, but with NavigationSplitView, the toolbar leaves a lot of empty space at the top (see below). Is there anything I can do to adjust this, or alternatively, continue to use the old style? Thanks!
12
3
2.7k
1w
iOS 26 (beta 7) setting .searchFocused programmatically does not work
Already filed a feedback in case this is a bug, but posting here in case I'm doing something wrong? I'd like the search field to automatically be displayed with the keyboard up when the view appears. This sample code works in iOS 18, but it does not work in iOS 26 beta 7 I also tried adding a delay to setting searchIsFocused = true but that did not help struct ContentView: View { var body: some View { NavigationStack { NavigationLink(destination: ListView()) { Label("Go to list", systemImage: "list.bullet") } } .ignoresSafeArea() } } struct ListView: View { @State private var searchText: String = "" @State private var searchIsPresented: Bool = false @FocusState private var searchIsFocused: Bool var body: some View { ScrollView { Text("Test") } .searchable(text: $searchText, isPresented: $searchIsPresented, placement: .automatic, prompt: "Search") .searchFocused($searchIsFocused) .onAppear { searchIsFocused = true } } }
5
1
150
1w
Unable to apply liquid glass effect on popover that is opened from a liquid glass container
When a popover is presented from a view that uses glassEffect(.regular.interactive()), I’m seeing mutually exclusive behavior: either the popover’s chrome (its navigation bar / toolbar) uses Liquid Glass or the originating control keeps its Liquid Glass “morph” behavior — but not both at the same time. There are two ways that I can enable Liquid Glass on the container: Option 1 (background capsule with .glassEffect) → The popover’s toolbar shows Liquid Glass, but the menu button loses its morph effect. Option 2 (.glassEffect applied to the HStack) → The menu button keeps the morph effect, but the popover’s toolbar does not have Liquid Glass. I'm using XCode 26.0.1, with latest iOS 26.0 stable simulator installed. Here's an example code to reproduce the issue: import PlaygroundSupport import SwiftUI // MARK: - TestView struct TestView: View { @State private var isPresented = false var body: some View { VStack { Spacer() HStack { Button("", systemImage: "plus") { isPresented = true } .popover(isPresented: $isPresented) { MyPopover() } Menu { Button("Option 1", action: {}) Button("Option 2", action: {}) Button("Option 3", action: {}) } label: { Image(systemName: "ellipsis") .frame(width: 40, height: 40) } } .padding(.horizontal) // Option 1 - The popover's toolbar will have liquid glass effect, but then the menu button loses liquid glass morph effect .background { Capsule() .fill(Color.white) .glassEffect(.regular.interactive()) } // Option 2 - The popover's toolbar will not have liquid glass effect, but the menu button keeps liquid glass morph effect // .glassEffect(.regular.interactive()) Spacer() } .frame(width: 400, height: 800) } } // MARK: - MyPopover private struct MyPopover: View { var body: some View { NavigationStack { VStack { ScrollView { Text( "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." ) .padding(.horizontal) } } .navigationTitle("Welcome") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("", systemImage: "xmark", action: {}) } } } .presentationCompactAdaptation(.popover) .frame(width: 300, height: 200) } } PlaygroundPage.current.setLiveView( TestView() ) Attached the screenshots for the difference.
1
0
61
1w
Is it still possible to change the color of unselected icons in a TabView?
Hi. I‘m making an app with SwiftUI for iOS 26, and found that the old ways of changing unselected icons color seem not working as they did in old versions of iOS. I tried these methods: TabView() { Tab { // some view here } label: { Label(title: { Text("something") }, icon: { Image(systemName: "checkmark.seal.fill") .foregroundStyle(.blue) } } } I wrapped Image with an if-else, but itisn't able to change any color even without if; struct ParentView: View { init() { UITabBar.appearance() .unselectedItemTintColor = UIColor.red } var body: some View { TabView() { // some tabs here } } } and an extension of above struct ParentView: View { init() { let tabBarAppearance = UITabBarAppearance() tabBarAppearance.configureWithOpaqueBackground() tabBarAppearance.backgroundColor = UIColor.green tabBarAppearance.stackedLayoutAppearance .selected.titleTextAttributes = [.foregroundColor: UIColor.red] tabBarAppearance.stackedLayoutAppearance.normal .titleTextAttributes = [.foregroundColor: UIColor.black] tabBarAppearance.stackedLayoutAppearance .normal.iconColor = UIColor.black tabBarAppearance.stackedLayoutAppearance .selected.iconColor = UIColor.red UITabBar.appearance() .scrollEdgeAppearance = tabBarAppearance UITabBar.appearance() .standardAppearance = tabBarAppearance UITabBar.appearance() .unselectedItemTintColor = .black } var body: some View { TabView() { // some tabs here } } } I read about this from reddit https://www.reddit.com/r/iOSProgramming/comments/1ftmfoa/tabbartabview_icon_and_text_colors_in_ios_18/, it successfully changes the color of the texts in the tabbar, but not the icons. After these, GitHub Copilot suggested me to draw two versions of icons, for different colors, which does work, but out of my capabilities. Is there any other ways to do this on new systems? Thank you very much for any replies.
1
0
84
1w
White flash using manageSubscriptionsSheet in SwiftUI
In SwiftUI I am using the manageSubscriptionsSheet modifier to open the iOS subscription screen. When this is presented it immediately flashes a white view and then animated the subscription screen up from the bottom, it looks pretty bad. The view I am calling manageSubscriptionsSheet on is presented in a sheet, so maybe trying to present the subscriptions view as well is causing the visual glitch. Any way to not have this white flashing view when opening the subscription screen?
0
0
106
1w
Extract Subview option missing in Xcode 26
Hi everyone, I recently updated to Xcode 26.0 and noticed that the “Extract Subview” refactoring option seems to be missing. Now, in Xcode 26, the only options I see under Editor -> Refactor -> are: Extract to Selection File Extract to Method Extract to Variable Extract All Occurrences But there’s no Extract Subview as there was before. Was Extract Subview intentionally removed in Xcode 26? Or is it hidden behind a new menu location or renamed?
5
5
398
1w
Present confirmationDialog from swipeActions in List
Hello, We use the .confirmationDialog() view modifier to present an alert when deleting an item in a list. Prior to iOS 26, this dialog appeared as an action sheet on iPhone. Following WWDC 25, my understanding is that on iOS 26 the dialog should appear as an action sheet over the originating view on iPhone. This is the behavior we observe in the built-in Messages and Mail apps when deleting an item (see the screenshot below). However, when using .confirmationDialog() on iOS 26, the dialog is displayed as a standard popover on iPhone. I haven’t been able to reproduce the new expected behavior. Here's a sample code: struct ContentView: View { @State var data: [String] = ["A", "B", "C"] @State var confirmationPresented: Bool = false var body: some View { List { ForEach(data, id: \.self) { item in Text(item) .confirmationDialog("Title", isPresented: $confirmationPresented, actions: { Button(action: { }, label: { Text("OK") }) }) .swipeActions { Button("Delete", systemImage: "trash", action: { confirmationPresented.toggle() }) .tint(Color.red) } } } } } Here's the result from this sample code: Is there an additional modifier or configuration required to enable the action sheet presentation on iPhone in iOS 26?
2
1
154
1w
Menu presentation in UIHostingController issues
Looking to see if anyone has experienced this issue, and is aware of any workarounds. With an app migrating towards SwiftUI Views but still using UIKit for primary navigation, my app makes use of UIHostingController to push SwiftUI Views onto a UINavigationController stack in a lot of areas. With iOS 26, I notice that SwiftUI's Menu view really struggles to present when contained in a UIHostingController. An error is logged to the console on presentation, and depending on the UI, the Menu won't present inside of it's container, or will jump around the screen. The bug, it seems is based in a private class UIReparentingView and I am curious if anyone has found a work around for this issue. The error reported is: Adding '_UIReparentingView' as a subview of UIHostingController.view is not supported and may result in a broken view hierarchy. Add your view above UIHostingController.view in a common superview or insert it into your SwiftUI content in a UIViewRepresentable instead. The simplest way to see this issue is to create a new storyboard based project. From the ViewController present a UIHostingController with a SwiftUI view that has a Menu and then simply tap to open the Menu. Thanks for any input!
6
2
275
1w
WKWebView Crashes on iOS During YouTube Playlist Playback
I’m encountering a consistent crash in WebKit when using WKWebView to play a YouTube playlist in my iOS app. Playback starts successfully, but the web process terminates during the second video in the playlist. This only occurs on physical devices, not in the simulator. Here’s a simplified Swift example of my setup: import SwiftUI import WebKit struct ContentView: View { private let playlistID = "PLig2mjpwQBZnghraUKGhCqc9eAy0UbpDN" var body: some View { YouTubeWebView(playlistID: playlistID) .edgesIgnoringSafeArea(.all) } } struct YouTubeWebView: UIViewRepresentable { let playlistID: String func makeUIView(context: Context) -> WKWebView { let config = WKWebViewConfiguration() config.allowsInlineMediaPlayback = true let webView = WKWebView(frame: .zero, configuration: config) webView.scrollView.isScrollEnabled = true let html = """ <!doctype html> <html> <head> <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0"> <style>body,html{height:100%;margin:0;background:#000}iframe{width:100%;height:100%;border:0}</style> </head> <body> <iframe src="https://www.youtube-nocookie.com/embed/videoseries?list=\(playlistID)&controls=1&rel=0&playsinline=1&iv_load_policy=3" frameborder="0" allow="encrypted-media; picture-in-picture; fullscreen" webkit-playsinline allowfullscreen ></iframe> </body> </html> """ webView.loadHTMLString(html, baseURL: nil) return webView } func updateUIView(_ uiView: WKWebView, context: Context) {} } #Preview { ContentView() } Observed behavior: First video plays without issue. Web process crashes when the second video in the playlist starts. Console logs show WebProcessProxy::didClose and repeated memory status messages. Using ProcessAssertion or background activity does not prevent the crash. Only occurs on physical devices; simulators do not reproduce the issue. Questions: Is there something I should change or add in my WKWebView setup or HTML/iframe to prevent the crash when playing the second video in a playlist on physical iOS devices? Is there an officially supported way to limit memory or prevent WebKit from terminating the web process during multi-video playback? Are there recommended patterns for playing YouTube playlists in a WKWebView on iOS without risking crashes? Any tips for debugging or configuring WKWebView to make it more stable for continuous playlist playback? Thanks in advance for any guidance!
2
0
307
1w