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

Action of full-width button in ToolbarItem is not triggered
To make a toolbar button that has the maximum width, I proceed as shown below with iOS 26. The appearance of the button is as expected, but its behavior is incorrect. The action is not triggered when tapping within the button, but outside its text. How to make the action triggered when tapping anywhere within the button ? import SwiftUI struct SampleView: View { var body: some View { NavigationStack { Text("") .toolbar { ToolbarItem(placement: .bottomBar) { Button(role: .confirm, action: self.action) { Text("Action") } .frame(maxWidth: .infinity) } } } } private func action() { print("Action Triggered !") } } #Preview { SampleView() }
2
0
110
4h
How to get Ask Siri context menu button
In my UIKit apps, collection view cells that have a context menu gain an Ask Siri item in iOS 27 without me doing anything. In my SwiftUI app I have a LazyVGrid containing a ForEach of CellView which is a Button that has a contextMenu, yet there’s no Ask Siri button in the context menu. What determines whether or not it will be added? What do I need to do to allow the system to add it?
2
0
64
1d
[OS27] Adaptive Layouts - TabView - Force Sidebar?
Hello, To support adaptive layouts on iOS27 I want to display the sidebar on landscape iPhone app windows. (Like in the old days of the iPhone 6 Plus... >.>) It appears that TabView ignores attempts to force it into sidebar mode even in the "Resize mode" of the device manager. Am I holding it wrong? Is this a bug? Apple is not clear about how their components should be behaving to support adaptive layouts, and if rumors are true, it will be important come this fall.
1
0
40
2d
TipKit: showing a popover tip on a SwiftUI toolbar button
Hi folks, there's currently a known issue in TipKit due to which it won't show popover tips on buttons that are inside a SwiftUI ToolbarItem. For example, if you try this code, the popover tip will not appear: ToolbarItem { Button(action: {...}) { Label("Tap here", systemImage: "gear") } .popoverTip(sampleTip) } There's an easy workaround for this issue. Just apply a style to the button. It can be any style. Some examples are bordered, borderless, plain and borderedProminent. Here's a fixed version of the above code: ToolbarItem { Button(action: {...}) { Label("Tap here", systemImage: "gear") } .buttonStyle(.plain) // Adding this line fixes the issue. .popoverTip(sampleTip) } Hope this helps anyone running into this issue.
12
12
6.2k
2d
Indentation in SwiftUI?
I need to display verse so that if a line exceeds the right margin, it is continued on the next line but indented. In UIKit this is easy by using NSParagraphStyle and headIndent and firstLineHeadIndent. But none of this is available on SwiftUI on the Apple Watch, which marks a big step back compared to WatchKit. Is there any way to display text indented in this way? I attach two screenshots, one with the indentation and one without. The one with indentation is far more readable!
Topic: UI Frameworks SubTopic: SwiftUI
0
0
26
3d
iOS 27 beta 1: .scrollEdgeEffectStyle(.soft) renders fully transparent above safeAreaBar
Feedback ID: FB23086400 On iOS 27 beta 1, .scrollEdgeEffectStyle(.soft, for: .top) on a List underneath a custom .safeAreaBar(edge: .top) no longer renders the progressive fade-blur. The top edge is fully transparent — scrolled rows pass under the bar with no visual treatment at all, as if scrollEdgeEffectDisabled() had been applied. What I've verified so far: .hard renders correctly in the exact same hierarchy; only .soft is affected. The same binary works correctly on iOS 26.x Xcode preview. I'm building with Xcode 26.3 (iOS 26 SDK). Minimal reproduction: import SwiftUI struct EdgeEffectRepro: View { enum Style: String, CaseIterable, Identifiable { case automatic, soft, hard var id: Self { self } var value: ScrollEdgeEffectStyle { switch self { case .automatic: .automatic case .soft: .soft case .hard: .hard } } } @State private var style: Style = .soft @State private var useSystemBarOnly = false var body: some View { NavigationStack { List(0..<60, id: \.self) { i in Text("Row \(i)") .frame(maxWidth: .infinity, alignment: .leading) .listRowBackground( i.isMultiple(of: 2) ? Color.orange.opacity(0.45) : Color.teal.opacity(0.45) ) } .scrollIndicators(.hidden) .scrollEdgeEffectStyle(style.value, for: .top) .safeAreaBar(edge: .top) { if !useSystemBarOnly { VStack(spacing: 8) { HStack { Text("Custom Top Bar") .font(.system(size: 28, weight: .bold)) Spacer() } HStack { Text("Second row (e.g. date range picker)") .font(.caption) .foregroundStyle(.secondary) Spacer() } } .padding(.horizontal) } } .safeAreaInset(edge: .bottom) { VStack(spacing: 8) { Picker("Edge effect style", selection: $style) { ForEach(Style.allCases) { Text($0.rawValue).tag($0) } } .pickerStyle(.segmented) Toggle("System bar only (control group)", isOn: $useSystemBarOnly) .font(.caption) } .padding() .background(.regularMaterial) } .navigationTitle("EdgeEffect Repro") .navigationBarTitleDisplayMode(.inline) } } } Steps: run on iOS 27 beta 1, set the picker to soft, scroll rows under the bar. Expected: fade-blur as on iOS 26. Actual: fully transparent. Switch to hard: renders fine.
1
4
312
3d
SwiftUI DragGesture is permanently cancelled (no terminal onEnded) by a trackpad magnify on macOS
Filed as FB23362414, with a minimal sample: https://github.com/mesqueeb/Swiftui-Gesture-Detection-Failures While a SwiftUI DragGesture is held (trackpad click-drag), a two-finger magnify (trackpad pinch) permanently cancels it: onChanged stops firing the instant the magnify is recognized. onEnded is never delivered — the gesture is torn down with no terminal event. Continued motion of the same, still-pressed finger after the pinch is not re-detected. The drag only recovers after a full release and re-press. Throughout, the AppKit NSEvent stream keeps delivering .leftMouseDragged (and a clean .leftMouseUp on release), so the OS is still tracking the drag — it's SwiftUI's gesture arbitration that discards it. No gesture composition avoids this: .simultaneousGesture, .highPriorityGesture, varying gesture order, and .exclusively(before:) in both directions were all tried; none delivers a terminal onEnded or resumes the drag after the pinch. Steps to reproduce (full sample in the repo — ./build.sh run): Press-hold and drag a shape with the trackpad (do not release). Without lifting the drag finger, perform a two-finger pinch. End the pinch and keep moving the same finger. Expected: onChanged continues for the still-pressed finger; onEnded fires when it's lifted. Actual: onChanged stops at the pinch and never resumes; onEnded never fires. Workaround: driving the gestures off AppKit NSEvent instead of SwiftUI works correctly — the sample has a toggle to switch between the two so you can compare side by side. Tested on macOS 26.3.1 (25D771280a) and macOS 27.0 Beta (26A5353q), Apple Silicon, built-in trackpad. Has anyone else run into this, or found a SwiftUI gesture composition that survives the pinch?
0
0
38
3d
iOS27: Bar Marks in Swift Charts exhibit multiple severe issues
Bar Marks in Swift Charts exhibit multiple severe issues on iOS27. Tested on: iPad Pro M2, 13", iOS27 Beta 2. Feedback submitted: FB23354502 Charts form a visual backbone of our app, and these issues render the chart unusable. Without a fix, we will not be able to support iOS27. The issues we identified: (1) We arrange mutually exclusive BarMarks on a time-based x-axis, inside a vertically scrolling Chart. We use init(xStart:, xEnd:, yStart: yEnd:), creating a visual timeline. Everything renders correctly on iOS26. On iOS27, many BarMarks are missing. (2) When we tap on a BarMark, we increase its height so make it appear selected. This works nicely in iOS26. The BarMark does not animate or change size at all on iOS27. (3) We have an outline around a BarMark, as part of styling. This uses .annotation(position: .overlay). The outline renders nicely in iOS26. On iOS27, the outline is rendered as a small circle inside the BarMark.
0
1
43
3d
OS27 LazyVGrid hops like crazy on scroll up.
I’m not sure if this is a ”care later in the summer” situation, but on beta 1, with an .adaptive Grid Item, a scrolling LazyVGrid will hop and “bounce” when scrolling back up from the bottom of the grid. I can see the scrollbar visibly hopping as item views are re-created. Anyone else seeing this?
5
1
165
4d
Adaptive Layouts iOS 27
I was experimenting with existing APIs using a NavigationSplitView and noticed that in the SwiftUI preview, resizing causes the component to switch between the content view and the sidebar. However, with the new DeviceHub tool, the app doesn’t detect the new size and stays in the content view. Is this expected? I would expect Navigation Split View to handle size changes automatically. Is this expected behaviour? FB23340323
0
0
51
4d
Auxiliary window control in Mac SwiftUI & SwiftData app
I've got a Mac Document App using SwiftUI and SwiftData. All is working well with the models editing, etc. There's a feature I need to implement, and can't seem to make it work. From the main window of the app, I need to be able to launch an auxilliary window containing a view-only representation of the model being edited. The required workflow is something like this: Open a document (SwiftData) Select a sub-model of the document Launch the aux window to display the view of the model data (must be in a separate window, because it will be on a different physical display) Continue making edits to the sub-model, as they are reflected in the other window So, below is the closest I've been able to come, and it's still not working at all. What happens with this code: Click on the "Present" button, the encounter-presentation Window opens, but never loads the data model or the view. It's just an empty window. This is the spot in the main view where the auxiliary window will be launched: @State var presenting: Presentation? = nil var presentingThisEncounter: Bool { presenting?.encounter.id == encounter.id } @Environment(\.openWindow) var openWindow ... if presentingThisEncounter { Button(action: { presenting = nil }) { Label("Stop", systemImage: "stop.fill") .padding(.horizontal, 4) } .preference(key: PresentationPreferenceKey.self, value: presenting) } else { Button(action: { presenting = Presentation(encounter: encounter, display: activeDisplay) openWindow(id: "encounter-presentation") }) { Label("Present", systemImage: "play.fill") .padding(.horizontal, 4) } .preference(key: PresentationPreferenceKey.self, value: nil) } Presentation is declared as: class Presentation: Observable, Equatable { Here's the contents of the App, where the DocumentGroup & model is instantiated, and the aux window is managed: @State var presentation: Presentation? var body: some Scene { DocumentGroup(editing: .encounterList, migrationPlan: EncounterListMigrationPlan.self) { ContentView() .onPreferenceChange(PresentationPreferenceKey.self) { self.presentation = $0 } } Window("Presentation", id: "encounter-presentation") { VStack { if let presentation = presentation { PresentingView(presentation: presentation) } } } } And the definition of PresentationPreferenceKey: struct PresentationPreferenceKey: PreferenceKey { static var defaultValue: Presentation? static func reduce(value: inout Presentation?, nextValue: () -> Presentation?) { value = nextValue() } }
3
0
708
4d
SwiftUI Equivalent of Nested Scroll Connection for Collapsing Profile Screens
I'm trying to build a profile-style screen similar to X (Twitter), Instagram, or YouTube. The layout is roughly: ┌──────────────────────────┐ │ Profile Header │ │ Cover image │ │ Avatar │ │ Bio / Stats │ └──────────────────────────┘ ┌──────────────────────────┐ │ Tab Bar │ │ Posts | Media | Likes │ └──────────────────────────┘ ┌──────────────────────────┐ │ Tab Content │ │ │ │ ScrollView / List │ │ OR │ │ Empty State VStack │ │ │ └──────────────────────────┘ Requirements: The profile header should collapse while scrolling up. The tab bar should remain pinned. Once the header is fully collapsed, the active tab's scroll view should start scrolling. While scrolling down, the active tab should scroll back to the top first, then the header should expand. Some tabs may contain: ScrollView + LazyVStack List a non-scrollable VStack (for empty states) The behavior should remain consistent regardless of which tab is active. This feels very similar to Jetpack Compose's NestedScrollConnection, where parent and child scroll containers can cooperatively consume scroll deltas. In SwiftUI, I have explored: ScrollView GeometryReader PreferenceKey Scroll offset tracking Custom UIScrollView wrappers A UIViewControllerRepresentable approach that intercepts pan gestures and coordinates scrolling manually However, I haven't found a SwiftUI-native way for a parent container and child scroll view to negotiate scroll consumption. My questions are: Does SwiftUI provide any equivalent to Compose's NestedScrollConnection? Is there a recommended way to implement this profile-screen pattern purely in SwiftUI? How are people handling cases where some tabs contain scrollable content while other tabs contain only static content? Is bridging to UIKit currently the only practical solution for this kind of coordinated scrolling behavior? Any guidance or examples would be greatly appreciated.
0
0
43
4d
State loss and sheets dismiss on backgrounding app
I've been hitting a weird SwiftUI bug with navigation and state loss and I've managed to reproduce in a very tiny sample project. I've submitted a Feedback FB21681608 but thought it was worth posting here incase any SwiftUI experts can see something obviously wrong. The bug With deeper levels of navigation hierarchy SwiftUI will dismiss views when backgrounding the app. Any work around would be appreciated. This happens in a real app where we have to navigate to a settings screen modally and then a complex flow with other sheets. Sample code Happens in the simulator and on device. import SwiftUI struct ContentView: View { @State private var isPresented = false var body: some View { Button("Show first sheet") { isPresented = true } .sheet(isPresented: $isPresented) { SheetView(count: 1) } } } struct SheetView: View { private enum Path: Hashable { case somePath } @State private var isPresented = false var count: Int var body: some View { NavigationStack { VStack { Text("Sheet \(count)") .font(.largeTitle) // To recreate bug show more than 4 sheets and then switch to the app switcher (CTRL-CMD-Shift-H). // All sheets after number 3 dismiss. Button("Show sheet: \(count + 1)") { isPresented = true } } .sheet(isPresented: $isPresented) { SheetView(count: count + 1) } // Comment out the `navigationDestination` below and the sheets don't dismiss when app goes to the background. // Or move this modifier above the .sheet modifier and the sheets don't dismiss. .navigationDestination(for: Path.self) { _ in fatalError() } } } }
Topic: UI Frameworks SubTopic: SwiftUI
4
3
296
4d
iOS 27 automatic resize
With iOS 27's automatic resizability for iPhone apps on iPad and in iPhone Mirroring, what's the recommended pattern for views that need genuinely different layouts at different size classes — is ViewThatFits the intended tool, or should we still branch on size class for larger structural changes? — Divya Ravi, Senior iOS Engineer
Topic: UI Frameworks SubTopic: SwiftUI
2
2
600
4d
tabViewBottomAccessory in 26.1: View's @State is lost when switching tabs
Any view that is content for the tabViewBottomAccessory API fails to retain its state as of the last couple of 26.1 betas (and RC). The loss of state happens (at least) when the currently selected tab is switched (filed as FB20901325). Here's code to reproduce the issue: struct ContentView: View { @State private var selectedTab = TabSelection.one enum TabSelection: Hashable { case one, two } var body: some View { TabView(selection: $selectedTab) { Tab("One", systemImage: "1.circle", value: .one) { BugExplanationView() } Tab("Two", systemImage: "2.circle", value: .two) { BugExplanationView() } } .tabViewBottomAccessory { AccessoryView() } } } struct AccessoryView: View { @State private var counter = 0 // This guy's state gets lost (as of iOS 26.1) var body: some View { Stepper("Counter: \(counter)", value: $counter) .padding(.horizontal) } } struct BugExplanationView: View { var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { Text("(1) Manipulate the counter state") Text("(2) Then switch tabs") Text("BUG: The counter state gets unexpectedly reset!") } .multilineTextAlignment(.leading) } } }
7
4
784
4d
MapKit MapStyle
Does anybody know if I'm missing something here? I'm using .mapStyle(.elevation(.realistic)), which enables the 3D map view, but it causes significant lag when driving in real life, especially at speeds above 50 mph. Everything works perfectly in the Simulator with no issues, but real world performance is much worse. The phone starts heating up almost immediately when driving in this mode through urban areas with 3D map data. Interestingly, the phone does not heat up on motorways, and performance is excellent there. (I guess because there's not so much 3D data to show on motorways) This mode looks fantastic and is one of the most requested features from my users, so I'm trying to figure out how to make it work properly. I've tested both SwiftUI and UIKit implementations and get the same result in both. Also I'm using an iPhone 17 Pro Max and an iPad 11, same result on both, including CarPlay import MapKit import CoreLocation struct ContentView: View { @State private var locationManager = LocationManagerDelegate() @State private var cameraPosition: MapCameraPosition = .userLocation(followsHeading: false, fallback: .automatic) @State private var isTracking: Bool = false var body: some View { Map(position: $cameraPosition) { UserAnnotation() } .mapStyle(.imagery(elevation: .realistic)) .onChange(of: locationManager.location) { _, location in guard isTracking, let location else { return } withAnimation(.linear(duration: 0.5)) { cameraPosition = .camera(MapCamera( centerCoordinate: location.coordinate, distance: 1000, heading: location.course, pitch: 60 )) } } .safeAreaInset(edge: .bottom) { // Added to the safeAreaInset to keep the Apple Logo visible Button("Track") { isTracking.toggle() locationManager.requestPermission() locationManager.startNavigating() } .buttonStyle(.glassProminent) .buttonSizing(.flexible) .controlSize(.extraLarge) .padding(.horizontal) } } } @MainActor @Observable final class LocationManagerDelegate: NSObject, CLLocationManagerDelegate { var location: CLLocation? var authorizationStatus: CLAuthorizationStatus = .notDetermined let manager = CLLocationManager() private var liveUpdateTask: Task<Void, Never>? override init() { super.init() manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyBestForNavigation manager.allowsBackgroundLocationUpdates = true authorizationStatus = manager.authorizationStatus } func requestPermission() { manager.requestWhenInUseAuthorization() } func startNavigating() { liveUpdateTask = Task { do { for try await update in CLLocationUpdate.liveUpdates(.automotiveNavigation) { guard let newLocation = update.location else { continue } self.location = newLocation } } catch { print("Live updates error: \(error)") } } } func stopNavigating() { liveUpdateTask?.cancel() liveUpdateTask = nil manager.requestLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { location = locations.last } func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { authorizationStatus = manager.authorizationStatus } } #Preview { ContentView() }
1
0
56
4d
iOS 27 / SwiftUI — Search tab .prominent doesn't morph on activation (field goes to top, tabs don't collapse)
I'm building an app with Xcode 27. I had trouble getting the tab bar to detach the search button onto the trailing side. I found that the search behaviour now works through the new .prominent treatment on iOS 27 (with Tab(role: .search)), and the detached button now displays correctly. My remaining problem is the activation behaviour. Expected (as in the system Phone / News / App Store apps): tapping the search button morphs the tab bar — the other tabs collapse into a single leading button and the search field expands at the bottom, centered. Actual: tapping the search tab pushes the search field to the top of the screen, attached to the navigation bar, with no morph animation and no tab collapse. Setup: Xcode 27.0 beta, iOS 27.0 on a physical iPhone Air Same with the Simulator (by the way... i also have some terrible lag with my app on Simulator + my iPhone even with a release version, but not throught TestFlight... strange...) 3 standard tabs + 1 search tab Single .searchable(text:) applied directly on the TabView (not on the inner NavigationStack) No .introspect or third-party modifiers on the search NavigationStack Is the morph + tab-collapse behaviour automatic for the search tab on iPhone, or does it require an additional modifier/configuration I'm missing? Can anyone confirm whether this morph works on a stable iOS 26 build with equivalent code? I suspect a regression in the 27.0 beta SDK, since the detached button works but the activation morph does not. I'm not yet an expert... so maybe i'm doing something wrong. I'll file Feedback if this is confirmed as a beta bug. Thanks.
Topic: UI Frameworks SubTopic: SwiftUI
1
0
73
5d
Push new views to sidebar when using NavigationPath
I have an existing app that uses NavigationSplitView with a detail view that is never changed and just updates to show changes in data. All navigation changes the sidebar only using NavigationLinks with .isDetailLink(false). Now I'm wanting to use NavigationPath with a simple router and enums. import SwiftUI @main struct NavRouterApp: App { @State private var router = Router() var body: some Scene { WindowGroup { NavigationStack(path: $router.navPath) { ContentView() .navigationDestination(for: AppRoute.self) { route in switch route { case .citizens: ContentView() .environment(router) case .citizen: EmptyView() .environment(router) case .tasform2: TASForm2View() .environment(router) case .start: StartView() .environment(router) case .editcharacteristics: EmptyView() .environment(router) case .basicdata(let citizen): BasicDataView(citizen: citizen) .environment(router) .navigationBarBackButtonHidden(true) case .characteristics: EmptyView() .environment(router) } } } .environment(router) } } } The problem is that pushing a subview now replaces the entire content instead of just the sidebar. Pushing a subview with NavigationSplitView would update the sidebar as desired but I would have to replace the detail view, which is not a good idea. I haven't been able to find any way to accomplish what I want. Suggestions?
Topic: UI Frameworks SubTopic: SwiftUI
6
0
114
5d
Action of full-width button in ToolbarItem is not triggered
To make a toolbar button that has the maximum width, I proceed as shown below with iOS 26. The appearance of the button is as expected, but its behavior is incorrect. The action is not triggered when tapping within the button, but outside its text. How to make the action triggered when tapping anywhere within the button ? import SwiftUI struct SampleView: View { var body: some View { NavigationStack { Text("") .toolbar { ToolbarItem(placement: .bottomBar) { Button(role: .confirm, action: self.action) { Text("Action") } .frame(maxWidth: .infinity) } } } } private func action() { print("Action Triggered !") } } #Preview { SampleView() }
Replies
2
Boosts
0
Views
110
Activity
4h
How to get Ask Siri context menu button
In my UIKit apps, collection view cells that have a context menu gain an Ask Siri item in iOS 27 without me doing anything. In my SwiftUI app I have a LazyVGrid containing a ForEach of CellView which is a Button that has a contextMenu, yet there’s no Ask Siri button in the context menu. What determines whether or not it will be added? What do I need to do to allow the system to add it?
Replies
2
Boosts
0
Views
64
Activity
1d
[OS27] Adaptive Layouts - TabView - Force Sidebar?
Hello, To support adaptive layouts on iOS27 I want to display the sidebar on landscape iPhone app windows. (Like in the old days of the iPhone 6 Plus... >.>) It appears that TabView ignores attempts to force it into sidebar mode even in the "Resize mode" of the device manager. Am I holding it wrong? Is this a bug? Apple is not clear about how their components should be behaving to support adaptive layouts, and if rumors are true, it will be important come this fall.
Replies
1
Boosts
0
Views
40
Activity
2d
TipKit: showing a popover tip on a SwiftUI toolbar button
Hi folks, there's currently a known issue in TipKit due to which it won't show popover tips on buttons that are inside a SwiftUI ToolbarItem. For example, if you try this code, the popover tip will not appear: ToolbarItem { Button(action: {...}) { Label("Tap here", systemImage: "gear") } .popoverTip(sampleTip) } There's an easy workaround for this issue. Just apply a style to the button. It can be any style. Some examples are bordered, borderless, plain and borderedProminent. Here's a fixed version of the above code: ToolbarItem { Button(action: {...}) { Label("Tap here", systemImage: "gear") } .buttonStyle(.plain) // Adding this line fixes the issue. .popoverTip(sampleTip) } Hope this helps anyone running into this issue.
Replies
12
Boosts
12
Views
6.2k
Activity
2d
Indentation in SwiftUI?
I need to display verse so that if a line exceeds the right margin, it is continued on the next line but indented. In UIKit this is easy by using NSParagraphStyle and headIndent and firstLineHeadIndent. But none of this is available on SwiftUI on the Apple Watch, which marks a big step back compared to WatchKit. Is there any way to display text indented in this way? I attach two screenshots, one with the indentation and one without. The one with indentation is far more readable!
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
26
Activity
3d
Segmented Picker overlapping/doubling text glitch inside ToolbarItem (.principal)
Hi everyone, I'm experiencing a weird visual glitch with PickerStyle(.segmented) placed inside a ToolbarItem(placement: .principal). When navigating between views or switching segments, the text doubles/overlaps temporarily during the transition animation (as shown in the screen recording).
Replies
0
Boosts
0
Views
37
Activity
3d
Segmented Picker overlapping/doubling text glitch inside ToolbarItem (.principal)
Hi everyone, I'm experiencing a weird visual glitch with PickerStyle(.segmented) placed inside a ToolbarItem(placement: .principal). When navigating between views or switching segments, the text doubles/overlaps temporarily during the transition animation (as shown in the screen recording).
Replies
0
Boosts
0
Views
34
Activity
3d
iOS 27 beta 1: .scrollEdgeEffectStyle(.soft) renders fully transparent above safeAreaBar
Feedback ID: FB23086400 On iOS 27 beta 1, .scrollEdgeEffectStyle(.soft, for: .top) on a List underneath a custom .safeAreaBar(edge: .top) no longer renders the progressive fade-blur. The top edge is fully transparent — scrolled rows pass under the bar with no visual treatment at all, as if scrollEdgeEffectDisabled() had been applied. What I've verified so far: .hard renders correctly in the exact same hierarchy; only .soft is affected. The same binary works correctly on iOS 26.x Xcode preview. I'm building with Xcode 26.3 (iOS 26 SDK). Minimal reproduction: import SwiftUI struct EdgeEffectRepro: View { enum Style: String, CaseIterable, Identifiable { case automatic, soft, hard var id: Self { self } var value: ScrollEdgeEffectStyle { switch self { case .automatic: .automatic case .soft: .soft case .hard: .hard } } } @State private var style: Style = .soft @State private var useSystemBarOnly = false var body: some View { NavigationStack { List(0..<60, id: \.self) { i in Text("Row \(i)") .frame(maxWidth: .infinity, alignment: .leading) .listRowBackground( i.isMultiple(of: 2) ? Color.orange.opacity(0.45) : Color.teal.opacity(0.45) ) } .scrollIndicators(.hidden) .scrollEdgeEffectStyle(style.value, for: .top) .safeAreaBar(edge: .top) { if !useSystemBarOnly { VStack(spacing: 8) { HStack { Text("Custom Top Bar") .font(.system(size: 28, weight: .bold)) Spacer() } HStack { Text("Second row (e.g. date range picker)") .font(.caption) .foregroundStyle(.secondary) Spacer() } } .padding(.horizontal) } } .safeAreaInset(edge: .bottom) { VStack(spacing: 8) { Picker("Edge effect style", selection: $style) { ForEach(Style.allCases) { Text($0.rawValue).tag($0) } } .pickerStyle(.segmented) Toggle("System bar only (control group)", isOn: $useSystemBarOnly) .font(.caption) } .padding() .background(.regularMaterial) } .navigationTitle("EdgeEffect Repro") .navigationBarTitleDisplayMode(.inline) } } } Steps: run on iOS 27 beta 1, set the picker to soft, scroll rows under the bar. Expected: fade-blur as on iOS 26. Actual: fully transparent. Switch to hard: renders fine.
Replies
1
Boosts
4
Views
312
Activity
3d
SwiftUI DragGesture is permanently cancelled (no terminal onEnded) by a trackpad magnify on macOS
Filed as FB23362414, with a minimal sample: https://github.com/mesqueeb/Swiftui-Gesture-Detection-Failures While a SwiftUI DragGesture is held (trackpad click-drag), a two-finger magnify (trackpad pinch) permanently cancels it: onChanged stops firing the instant the magnify is recognized. onEnded is never delivered — the gesture is torn down with no terminal event. Continued motion of the same, still-pressed finger after the pinch is not re-detected. The drag only recovers after a full release and re-press. Throughout, the AppKit NSEvent stream keeps delivering .leftMouseDragged (and a clean .leftMouseUp on release), so the OS is still tracking the drag — it's SwiftUI's gesture arbitration that discards it. No gesture composition avoids this: .simultaneousGesture, .highPriorityGesture, varying gesture order, and .exclusively(before:) in both directions were all tried; none delivers a terminal onEnded or resumes the drag after the pinch. Steps to reproduce (full sample in the repo — ./build.sh run): Press-hold and drag a shape with the trackpad (do not release). Without lifting the drag finger, perform a two-finger pinch. End the pinch and keep moving the same finger. Expected: onChanged continues for the still-pressed finger; onEnded fires when it's lifted. Actual: onChanged stops at the pinch and never resumes; onEnded never fires. Workaround: driving the gestures off AppKit NSEvent instead of SwiftUI works correctly — the sample has a toggle to switch between the two so you can compare side by side. Tested on macOS 26.3.1 (25D771280a) and macOS 27.0 Beta (26A5353q), Apple Silicon, built-in trackpad. Has anyone else run into this, or found a SwiftUI gesture composition that survives the pinch?
Replies
0
Boosts
0
Views
38
Activity
3d
iOS27: Bar Marks in Swift Charts exhibit multiple severe issues
Bar Marks in Swift Charts exhibit multiple severe issues on iOS27. Tested on: iPad Pro M2, 13", iOS27 Beta 2. Feedback submitted: FB23354502 Charts form a visual backbone of our app, and these issues render the chart unusable. Without a fix, we will not be able to support iOS27. The issues we identified: (1) We arrange mutually exclusive BarMarks on a time-based x-axis, inside a vertically scrolling Chart. We use init(xStart:, xEnd:, yStart: yEnd:), creating a visual timeline. Everything renders correctly on iOS26. On iOS27, many BarMarks are missing. (2) When we tap on a BarMark, we increase its height so make it appear selected. This works nicely in iOS26. The BarMark does not animate or change size at all on iOS27. (3) We have an outline around a BarMark, as part of styling. This uses .annotation(position: .overlay). The outline renders nicely in iOS26. On iOS27, the outline is rendered as a small circle inside the BarMark.
Replies
0
Boosts
1
Views
43
Activity
3d
OS27 LazyVGrid hops like crazy on scroll up.
I’m not sure if this is a ”care later in the summer” situation, but on beta 1, with an .adaptive Grid Item, a scrolling LazyVGrid will hop and “bounce” when scrolling back up from the bottom of the grid. I can see the scrollbar visibly hopping as item views are re-created. Anyone else seeing this?
Replies
5
Boosts
1
Views
165
Activity
4d
Adaptive Layouts iOS 27
I was experimenting with existing APIs using a NavigationSplitView and noticed that in the SwiftUI preview, resizing causes the component to switch between the content view and the sidebar. However, with the new DeviceHub tool, the app doesn’t detect the new size and stays in the content view. Is this expected? I would expect Navigation Split View to handle size changes automatically. Is this expected behaviour? FB23340323
Replies
0
Boosts
0
Views
51
Activity
4d
Auxiliary window control in Mac SwiftUI & SwiftData app
I've got a Mac Document App using SwiftUI and SwiftData. All is working well with the models editing, etc. There's a feature I need to implement, and can't seem to make it work. From the main window of the app, I need to be able to launch an auxilliary window containing a view-only representation of the model being edited. The required workflow is something like this: Open a document (SwiftData) Select a sub-model of the document Launch the aux window to display the view of the model data (must be in a separate window, because it will be on a different physical display) Continue making edits to the sub-model, as they are reflected in the other window So, below is the closest I've been able to come, and it's still not working at all. What happens with this code: Click on the "Present" button, the encounter-presentation Window opens, but never loads the data model or the view. It's just an empty window. This is the spot in the main view where the auxiliary window will be launched: @State var presenting: Presentation? = nil var presentingThisEncounter: Bool { presenting?.encounter.id == encounter.id } @Environment(\.openWindow) var openWindow ... if presentingThisEncounter { Button(action: { presenting = nil }) { Label("Stop", systemImage: "stop.fill") .padding(.horizontal, 4) } .preference(key: PresentationPreferenceKey.self, value: presenting) } else { Button(action: { presenting = Presentation(encounter: encounter, display: activeDisplay) openWindow(id: "encounter-presentation") }) { Label("Present", systemImage: "play.fill") .padding(.horizontal, 4) } .preference(key: PresentationPreferenceKey.self, value: nil) } Presentation is declared as: class Presentation: Observable, Equatable { Here's the contents of the App, where the DocumentGroup & model is instantiated, and the aux window is managed: @State var presentation: Presentation? var body: some Scene { DocumentGroup(editing: .encounterList, migrationPlan: EncounterListMigrationPlan.self) { ContentView() .onPreferenceChange(PresentationPreferenceKey.self) { self.presentation = $0 } } Window("Presentation", id: "encounter-presentation") { VStack { if let presentation = presentation { PresentingView(presentation: presentation) } } } } And the definition of PresentationPreferenceKey: struct PresentationPreferenceKey: PreferenceKey { static var defaultValue: Presentation? static func reduce(value: inout Presentation?, nextValue: () -> Presentation?) { value = nextValue() } }
Replies
3
Boosts
0
Views
708
Activity
4d
SwiftUI Equivalent of Nested Scroll Connection for Collapsing Profile Screens
I'm trying to build a profile-style screen similar to X (Twitter), Instagram, or YouTube. The layout is roughly: ┌──────────────────────────┐ │ Profile Header │ │ Cover image │ │ Avatar │ │ Bio / Stats │ └──────────────────────────┘ ┌──────────────────────────┐ │ Tab Bar │ │ Posts | Media | Likes │ └──────────────────────────┘ ┌──────────────────────────┐ │ Tab Content │ │ │ │ ScrollView / List │ │ OR │ │ Empty State VStack │ │ │ └──────────────────────────┘ Requirements: The profile header should collapse while scrolling up. The tab bar should remain pinned. Once the header is fully collapsed, the active tab's scroll view should start scrolling. While scrolling down, the active tab should scroll back to the top first, then the header should expand. Some tabs may contain: ScrollView + LazyVStack List a non-scrollable VStack (for empty states) The behavior should remain consistent regardless of which tab is active. This feels very similar to Jetpack Compose's NestedScrollConnection, where parent and child scroll containers can cooperatively consume scroll deltas. In SwiftUI, I have explored: ScrollView GeometryReader PreferenceKey Scroll offset tracking Custom UIScrollView wrappers A UIViewControllerRepresentable approach that intercepts pan gestures and coordinates scrolling manually However, I haven't found a SwiftUI-native way for a parent container and child scroll view to negotiate scroll consumption. My questions are: Does SwiftUI provide any equivalent to Compose's NestedScrollConnection? Is there a recommended way to implement this profile-screen pattern purely in SwiftUI? How are people handling cases where some tabs contain scrollable content while other tabs contain only static content? Is bridging to UIKit currently the only practical solution for this kind of coordinated scrolling behavior? Any guidance or examples would be greatly appreciated.
Replies
0
Boosts
0
Views
43
Activity
4d
State loss and sheets dismiss on backgrounding app
I've been hitting a weird SwiftUI bug with navigation and state loss and I've managed to reproduce in a very tiny sample project. I've submitted a Feedback FB21681608 but thought it was worth posting here incase any SwiftUI experts can see something obviously wrong. The bug With deeper levels of navigation hierarchy SwiftUI will dismiss views when backgrounding the app. Any work around would be appreciated. This happens in a real app where we have to navigate to a settings screen modally and then a complex flow with other sheets. Sample code Happens in the simulator and on device. import SwiftUI struct ContentView: View { @State private var isPresented = false var body: some View { Button("Show first sheet") { isPresented = true } .sheet(isPresented: $isPresented) { SheetView(count: 1) } } } struct SheetView: View { private enum Path: Hashable { case somePath } @State private var isPresented = false var count: Int var body: some View { NavigationStack { VStack { Text("Sheet \(count)") .font(.largeTitle) // To recreate bug show more than 4 sheets and then switch to the app switcher (CTRL-CMD-Shift-H). // All sheets after number 3 dismiss. Button("Show sheet: \(count + 1)") { isPresented = true } } .sheet(isPresented: $isPresented) { SheetView(count: count + 1) } // Comment out the `navigationDestination` below and the sheets don't dismiss when app goes to the background. // Or move this modifier above the .sheet modifier and the sheets don't dismiss. .navigationDestination(for: Path.self) { _ in fatalError() } } } }
Topic: UI Frameworks SubTopic: SwiftUI
Replies
4
Boosts
3
Views
296
Activity
4d
iOS 27 automatic resize
With iOS 27's automatic resizability for iPhone apps on iPad and in iPhone Mirroring, what's the recommended pattern for views that need genuinely different layouts at different size classes — is ViewThatFits the intended tool, or should we still branch on size class for larger structural changes? — Divya Ravi, Senior iOS Engineer
Topic: UI Frameworks SubTopic: SwiftUI
Replies
2
Boosts
2
Views
600
Activity
4d
tabViewBottomAccessory in 26.1: View's @State is lost when switching tabs
Any view that is content for the tabViewBottomAccessory API fails to retain its state as of the last couple of 26.1 betas (and RC). The loss of state happens (at least) when the currently selected tab is switched (filed as FB20901325). Here's code to reproduce the issue: struct ContentView: View { @State private var selectedTab = TabSelection.one enum TabSelection: Hashable { case one, two } var body: some View { TabView(selection: $selectedTab) { Tab("One", systemImage: "1.circle", value: .one) { BugExplanationView() } Tab("Two", systemImage: "2.circle", value: .two) { BugExplanationView() } } .tabViewBottomAccessory { AccessoryView() } } } struct AccessoryView: View { @State private var counter = 0 // This guy's state gets lost (as of iOS 26.1) var body: some View { Stepper("Counter: \(counter)", value: $counter) .padding(.horizontal) } } struct BugExplanationView: View { var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { Text("(1) Manipulate the counter state") Text("(2) Then switch tabs") Text("BUG: The counter state gets unexpectedly reset!") } .multilineTextAlignment(.leading) } } }
Replies
7
Boosts
4
Views
784
Activity
4d
MapKit MapStyle
Does anybody know if I'm missing something here? I'm using .mapStyle(.elevation(.realistic)), which enables the 3D map view, but it causes significant lag when driving in real life, especially at speeds above 50 mph. Everything works perfectly in the Simulator with no issues, but real world performance is much worse. The phone starts heating up almost immediately when driving in this mode through urban areas with 3D map data. Interestingly, the phone does not heat up on motorways, and performance is excellent there. (I guess because there's not so much 3D data to show on motorways) This mode looks fantastic and is one of the most requested features from my users, so I'm trying to figure out how to make it work properly. I've tested both SwiftUI and UIKit implementations and get the same result in both. Also I'm using an iPhone 17 Pro Max and an iPad 11, same result on both, including CarPlay import MapKit import CoreLocation struct ContentView: View { @State private var locationManager = LocationManagerDelegate() @State private var cameraPosition: MapCameraPosition = .userLocation(followsHeading: false, fallback: .automatic) @State private var isTracking: Bool = false var body: some View { Map(position: $cameraPosition) { UserAnnotation() } .mapStyle(.imagery(elevation: .realistic)) .onChange(of: locationManager.location) { _, location in guard isTracking, let location else { return } withAnimation(.linear(duration: 0.5)) { cameraPosition = .camera(MapCamera( centerCoordinate: location.coordinate, distance: 1000, heading: location.course, pitch: 60 )) } } .safeAreaInset(edge: .bottom) { // Added to the safeAreaInset to keep the Apple Logo visible Button("Track") { isTracking.toggle() locationManager.requestPermission() locationManager.startNavigating() } .buttonStyle(.glassProminent) .buttonSizing(.flexible) .controlSize(.extraLarge) .padding(.horizontal) } } } @MainActor @Observable final class LocationManagerDelegate: NSObject, CLLocationManagerDelegate { var location: CLLocation? var authorizationStatus: CLAuthorizationStatus = .notDetermined let manager = CLLocationManager() private var liveUpdateTask: Task<Void, Never>? override init() { super.init() manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyBestForNavigation manager.allowsBackgroundLocationUpdates = true authorizationStatus = manager.authorizationStatus } func requestPermission() { manager.requestWhenInUseAuthorization() } func startNavigating() { liveUpdateTask = Task { do { for try await update in CLLocationUpdate.liveUpdates(.automotiveNavigation) { guard let newLocation = update.location else { continue } self.location = newLocation } } catch { print("Live updates error: \(error)") } } } func stopNavigating() { liveUpdateTask?.cancel() liveUpdateTask = nil manager.requestLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { location = locations.last } func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { authorizationStatus = manager.authorizationStatus } } #Preview { ContentView() }
Replies
1
Boosts
0
Views
56
Activity
4d
iOS 27 / SwiftUI — Search tab .prominent doesn't morph on activation (field goes to top, tabs don't collapse)
I'm building an app with Xcode 27. I had trouble getting the tab bar to detach the search button onto the trailing side. I found that the search behaviour now works through the new .prominent treatment on iOS 27 (with Tab(role: .search)), and the detached button now displays correctly. My remaining problem is the activation behaviour. Expected (as in the system Phone / News / App Store apps): tapping the search button morphs the tab bar — the other tabs collapse into a single leading button and the search field expands at the bottom, centered. Actual: tapping the search tab pushes the search field to the top of the screen, attached to the navigation bar, with no morph animation and no tab collapse. Setup: Xcode 27.0 beta, iOS 27.0 on a physical iPhone Air Same with the Simulator (by the way... i also have some terrible lag with my app on Simulator + my iPhone even with a release version, but not throught TestFlight... strange...) 3 standard tabs + 1 search tab Single .searchable(text:) applied directly on the TabView (not on the inner NavigationStack) No .introspect or third-party modifiers on the search NavigationStack Is the morph + tab-collapse behaviour automatic for the search tab on iPhone, or does it require an additional modifier/configuration I'm missing? Can anyone confirm whether this morph works on a stable iOS 26 build with equivalent code? I suspect a regression in the 27.0 beta SDK, since the detached button works but the activation morph does not. I'm not yet an expert... so maybe i'm doing something wrong. I'll file Feedback if this is confirmed as a beta bug. Thanks.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
0
Views
73
Activity
5d
Push new views to sidebar when using NavigationPath
I have an existing app that uses NavigationSplitView with a detail view that is never changed and just updates to show changes in data. All navigation changes the sidebar only using NavigationLinks with .isDetailLink(false). Now I'm wanting to use NavigationPath with a simple router and enums. import SwiftUI @main struct NavRouterApp: App { @State private var router = Router() var body: some Scene { WindowGroup { NavigationStack(path: $router.navPath) { ContentView() .navigationDestination(for: AppRoute.self) { route in switch route { case .citizens: ContentView() .environment(router) case .citizen: EmptyView() .environment(router) case .tasform2: TASForm2View() .environment(router) case .start: StartView() .environment(router) case .editcharacteristics: EmptyView() .environment(router) case .basicdata(let citizen): BasicDataView(citizen: citizen) .environment(router) .navigationBarBackButtonHidden(true) case .characteristics: EmptyView() .environment(router) } } } .environment(router) } } } The problem is that pushing a subview now replaces the entire content instead of just the sidebar. Pushing a subview with NavigationSplitView would update the sidebar as desired but I would have to replace the detail view, which is not a good idea. I haven't been able to find any way to accomplish what I want. Suggestions?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
6
Boosts
0
Views
114
Activity
5d