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

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
47
1h
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() }
0
0
67
1d
UINavigationItemRenameDelegate does not work in IOS 16
I have an iPad app which is trying to support document renaming in the title bar. For IOS 17+ I set the renameDelegate to the document instance and it works fine. For IOS 16 I need to create an actual delegate, but no matter how I structure the code it fails with a permission error: Rename failed: “original_file_name” couldn’t be moved because you don’t have permission to access “Desktop”. It seems to always happen accessing the parent directory. I have tried using the file coordinator as well with the same result. It seems impossible to implement unless the callback contains a security permissioned url for the parent directory. Is there anyway to make this work in IOS 16 in the sandbox? Do I have to create my own rename functionality using a FilePicker? Seems like this should be built in like it is in MacOS, or even IOS17+ Here is the code: extension DocumentWindow : UINavigationItemRenameDelegate { func navigationItem(_ navigationItem: UINavigationItem, didEndRenamingWith title: String) { guard let doc = document else { return } let oldURL = doc.fileURL let newURL = oldURL.deletingLastPathComponent() .appendingPathComponent(title) .appendingPathExtension(oldURL.pathExtension) if newURL == oldURL { return } let access = oldURL.startAccessingSecurityScopedResource() defer { if access { oldURL.stopAccessingSecurityScopedResource() }} do { try FileManager.default.moveItem(at: oldURL, to: newURL) } catch { print("Rename failed: \(error.localizedDescription)") } // // // 1. Jump to a background queue to avoid the deadlock // DispatchQueue.global(qos: .userInitiated).async { // let coordinator = NSFileCoordinator(filePresenter: doc) // var error: NSError? // // // coordinator.coordinate(writingItemAt: oldURL, error: &error) { outOld in // do { // // 2. Perform the actual rename // try FileManager.default.moveItem(at: outOLD, to: newURL) // } catch { // print("Rename failed: \(error.localizedDescription)") // } // } // // if let error = error { // print("Coordination error: \(error.localizedDescription)") // } // } } // 2. Optional: Validation (e.g., prevent empty names) func navigationItem(_ navigationItem: UINavigationItem, shouldEndRenamingWith title: String) -> Bool { return !title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty } }
0
0
27
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
31
1d
Application Hangs with Nested LazyVStack When Accessibility Inspector is Active
Description I've encountered a consistent hang/freeze issue in SwiftUI applications when using nested LazyVStack containers with Accessibility Inspector (simulator) or VoiceOver (physical device) enabled. The application becomes completely unresponsive and must be force-quit. Importantly, this hang occurs in a minimal SwiftUI project with no third-party dependencies, suggesting this is a framework-level issue with the interaction between SwiftUI's lazy view lifecycle and the accessibility system. Reproduction Steps I've created a minimal reproduction project available here: https://github.com/pendo-io/SwiftUI_Hang_Reproduction To Reproduce: Create a SwiftUI view with the following nested LazyVStack structure: struct NestedLazyVStackView: View { @State private var outerSections: [Int] = [] @State private var innerRows: [Int: [Int]] = [:] var body: some View { ScrollView { LazyVStack(alignment: .leading, spacing: 24) { ForEach(outerSections, id: \.self) { section in VStack(alignment: .leading, spacing: 8) { Text("Section #\(section)") // Nested LazyVStack LazyVStack(alignment: .leading, spacing: 2) { ForEach(innerRows[section] ?? [], id: \.self) { row in Text("Section #\(section) - Row #\(row)") .onAppear { // Load more data when row appears loadMoreInner(section: section) } } } } .onAppear { // Load more sections when section appears loadMoreOuter() } } } } } } Enable Accessibility Inspector in iOS Simulator: Xcode → Open Developer Tool → Accessibility Inspector Select your running simulator Enable Inspection mode (eye icon) Navigate to the view and start scrolling Result: The application hangs and becomes unresponsive within a few seconds of scrolling Expected Behavior The application should remain responsive when Accessibility Inspector or VoiceOver is enabled, allowing users to scroll through nested lazy containers without freezing. Actual Behavior The application freezes/hangs completely CPU usage may spike The app must be force-quit to recover The hang occurs consistently and is reproducible Workaround 1: Replace inner LazyVStack with VStack LazyVStack { ForEach(...) { section in VStack { // ← Changed from LazyVStack ForEach(...) { row in ... } } } } Workaround 2: Embed in TabView TabView { NavigationStack { NestedLazyVStackView() // ← Same nested structure, but no hang } .tabItem { ... } } Interestingly, wrapping the entire navigation stack in a TabView prevents the hang entirely, even with the nested LazyVStack structure intact. Questions for Apple Is there a known issue with nested LazyVStack containers and accessibility traversal? Why does wrapping the view in a TabView prevent the hang? Are there recommended patterns for using nested lazy containers with accessibility support? Is this a timing issue, a deadlock, or an infinite loop in the accessibility system? Why that happens? Reproduction Project A complete, minimal reproduction project is available at: https://github.com/pendo-io/SwiftUI_Hang_Reproduction
8
0
594
2d
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
306
2d
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
30
2d
Are there any ways to prevent app record/capture on macOS
I'm looking for a way to prevent my app from displaying in screenshots and screen recordings. There appears to be plenty of options for UIKit/iOS but nothing I can find for macOS. userDidTakeScreenshotNotification @Environment(.sceneCaptureState) private var captureState Obviously it's possible though as I remember back in the day you couldn't take screenshots of the DVD Player etc.
0
0
38
2d
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
152
3d
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
39
3d
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
693
3d
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
31
3d
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
774
3d
Snippet Views don't render consistently, width not always respected
I've created a Snippet for my iOS app which I want to be able to run from the LockScreen via a Shortcuts widget. All works fine except when I run the shortcut and the App Snippet appears, it doesn't always render the SwiftUI view in the same way. Sometimes the width boundaries are respected and sometimes not. I've tested this on iOS 26.1 and iOS 26.2 beta 3 I think this is a bug but it would be great if anyone could see what I might be doing wrong if it's not. Incase it is a bug I've filed a feedback (FB21076429) and I've created a stripped down sample project showing the issue and added screenshots showing the issue. Basic code to reproduce issue: // Intent.swift // SnippetBug import AppIntents import Foundation import SwiftUI struct SnippetEntryIntent: AppIntent { static let title: LocalizedStringResource = "Open Snippet" static let description = IntentDescription("Shows a snippet.") // Don’t open the app – stay in the snippet surface. static let openAppWhenRun: Bool = false func perform() async throws -> some ShowsSnippetIntent { .result(snippetIntent: TestSnippetIntent()) } } struct TestSnippetIntent: SnippetIntent { static let title: LocalizedStringResource = "Snippet Intent" static let description = IntentDescription("Action from snippet.") @MainActor func perform() async throws -> some IntentResult & ShowsSnippetView { .result(view: SnippetView(model: SnippetModel.shared)) } } @MainActor final class SnippetModel { static let shared = SnippetModel() private init() { } } struct SnippetView: View { let model: SnippetModel var body: some View { HStack { Text("Test Snippet with information") Spacer() Image(systemName: "heart") }.font(.headline) } } struct Shortcuts: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: SnippetEntryIntent(), phrases: [ "Snippet for \(.applicationName)", "Test Snippet \(.applicationName)" ], shortTitle: "Snippet", systemImageName: "barcode" ) } } You also need these lines in your main App entry point: import AppIntents @main struct SnippetBugApp: App { init() { let model = SnippetModel.shared AppDependencyManager.shared.add(dependency: model) } var body: some Scene { WindowGroup { ContentView() } } } This is correct This is incorrect
2
1
327
1w
VideoPlayer crashes on Archive build
I have found that following code runs without issue from Xcode, either in Debug or Release mode, yet crashes when running from the binary produced by archiving - i.e. what will be sent to the app store. import SwiftUI import AVKit @main struct tcApp: App { var body: some Scene { WindowGroup { VideoPlayer(player: nil) } } } This is the most stripped down code that shows the issue. One can try and point the VideoPlayer at a file and the same issue will occur. I've attached the crash log: Crash log Please note that this was seen with Xcode 26.2 and MacOS 26.2.
2
0
814
1w
Different keyboards show up for KeyboardType .decimalPad
Environment: iOS 26; iPad Mini/Air/Pro Problem: In a TextField, I am using a keyboard with the type .decimalPad. When I initially tap into the TextField, the "popover" keyboard (i.e. the decimalPad) shows up and focusses the TextField. However, when I click outside the TextField (to dismiss the keyboard), the TextField is still focussed (the keyboard was dismissed though). When reentering in the TextField, another keyboard (from the bottom of the screen) appears (most likely .numeric). Does anybody know how to solve this? What I already tried: I tried listening to the dismissal of the keyboard to manually set the FocusState to nil. However, the dismissal of the "popover/decimal" keyboard is not recognized as such a dismissal. I also tried to build a custom component out of that, but then I lose the TextField behavior, conflicting with HIG.
2
0
160
1w
Delay when using ResultsObserver over @Query?
I was testing how to use ResultsObserver on a ViewModel in SwiftData. In Xcode 27, Developer v1, I have the following view import SwiftUI import SwiftData @Model class TaskItem { var name: String var priority: Int init(name: String, priority: Int) { self.name = name self.priority = priority } } @Observable @MainActor class RandomViewModel { let observer: ResultsObserver<TaskItem, Never> @ObservationIgnored private var token: ObservationTracking.Token? var tasks: FetchResultsCollection<TaskItem> { observer.results } init(context: ModelContext) { let descriptor = FetchDescriptor<TaskItem>( sortBy: [SortDescriptor(\.name, order: .reverse)] ) observer = try! ResultsObserver(fetchDescriptor: descriptor, modelContext: context) } } struct RandomView: View { @State var viewModel: RandomViewModel? @Environment(\.modelContext) private var modelContext var body: some View { VStack { if let viewModel { List(viewModel.tasks) { foo in Text(foo.name) } .toolbar { ToolbarItem(placement: .primaryAction) { Button("Add Task") { let task = TaskItem(name: "ZZ New Task \(viewModel.observer.results.count + 1)", priority: 2) print("add \(task.name)") modelContext.insert(task) } } } } else { Text("Hello, World!") } } .task { if viewModel == nil { viewModel = RandomViewModel(context: modelContext) } } } } func testContainer() -> ModelContainer { let schema = Schema([ Item.self, TaskItem.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true) let container = try! ModelContainer(for: schema, configurations: [modelConfiguration]) let modelContext = container.mainContext for i in 1...20 { let item = TaskItem(name: "Sample Task \(i)", priority: Int.random(in: 1...5)) modelContext.insert(item) } return container } #Preview { NavigationStack { RandomView() } .modelContainer(testContainer()) } When I run the Preview or the simulator, the UI takes a while to actually load and show the results. If I try a version using @Query this doesn't happen import SwiftData import SwiftUI struct RandomQueryView: View { @Environment(\.modelContext) private var modelContext @Query(sort: [SortDescriptor(\TaskItem.name, order: .reverse)]) private var tasks: [TaskItem] var body: some View { List(tasks) { task in Text(task.name) } .toolbar { ToolbarItem(placement: .primaryAction) { Button("Add Task") { let task = TaskItem(name: "ZZ New Task \(tasks.count + 1)", priority: 2) print("add \(task.name)") modelContext.insert(task) } } } } } #Preview { NavigationStack { RandomQueryView() } .modelContainer(testContainer()) } Is this a bug in SwiftData ResultsObserver? or am I using it wrong? I add a recording of my simulator showing the difference
1
0
120
1w
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
47
Activity
1h
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
0
Boosts
0
Views
67
Activity
1d
UINavigationItemRenameDelegate does not work in IOS 16
I have an iPad app which is trying to support document renaming in the title bar. For IOS 17+ I set the renameDelegate to the document instance and it works fine. For IOS 16 I need to create an actual delegate, but no matter how I structure the code it fails with a permission error: Rename failed: “original_file_name” couldn’t be moved because you don’t have permission to access “Desktop”. It seems to always happen accessing the parent directory. I have tried using the file coordinator as well with the same result. It seems impossible to implement unless the callback contains a security permissioned url for the parent directory. Is there anyway to make this work in IOS 16 in the sandbox? Do I have to create my own rename functionality using a FilePicker? Seems like this should be built in like it is in MacOS, or even IOS17+ Here is the code: extension DocumentWindow : UINavigationItemRenameDelegate { func navigationItem(_ navigationItem: UINavigationItem, didEndRenamingWith title: String) { guard let doc = document else { return } let oldURL = doc.fileURL let newURL = oldURL.deletingLastPathComponent() .appendingPathComponent(title) .appendingPathExtension(oldURL.pathExtension) if newURL == oldURL { return } let access = oldURL.startAccessingSecurityScopedResource() defer { if access { oldURL.stopAccessingSecurityScopedResource() }} do { try FileManager.default.moveItem(at: oldURL, to: newURL) } catch { print("Rename failed: \(error.localizedDescription)") } // // // 1. Jump to a background queue to avoid the deadlock // DispatchQueue.global(qos: .userInitiated).async { // let coordinator = NSFileCoordinator(filePresenter: doc) // var error: NSError? // // // coordinator.coordinate(writingItemAt: oldURL, error: &error) { outOld in // do { // // 2. Perform the actual rename // try FileManager.default.moveItem(at: outOLD, to: newURL) // } catch { // print("Rename failed: \(error.localizedDescription)") // } // } // // if let error = error { // print("Coordination error: \(error.localizedDescription)") // } // } } // 2. Optional: Validation (e.g., prevent empty names) func navigationItem(_ navigationItem: UINavigationItem, shouldEndRenamingWith title: String) -> Bool { return !title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty } }
Replies
0
Boosts
0
Views
27
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
31
Activity
1d
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
29
Activity
2d
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
27
Activity
2d
Application Hangs with Nested LazyVStack When Accessibility Inspector is Active
Description I've encountered a consistent hang/freeze issue in SwiftUI applications when using nested LazyVStack containers with Accessibility Inspector (simulator) or VoiceOver (physical device) enabled. The application becomes completely unresponsive and must be force-quit. Importantly, this hang occurs in a minimal SwiftUI project with no third-party dependencies, suggesting this is a framework-level issue with the interaction between SwiftUI's lazy view lifecycle and the accessibility system. Reproduction Steps I've created a minimal reproduction project available here: https://github.com/pendo-io/SwiftUI_Hang_Reproduction To Reproduce: Create a SwiftUI view with the following nested LazyVStack structure: struct NestedLazyVStackView: View { @State private var outerSections: [Int] = [] @State private var innerRows: [Int: [Int]] = [:] var body: some View { ScrollView { LazyVStack(alignment: .leading, spacing: 24) { ForEach(outerSections, id: \.self) { section in VStack(alignment: .leading, spacing: 8) { Text("Section #\(section)") // Nested LazyVStack LazyVStack(alignment: .leading, spacing: 2) { ForEach(innerRows[section] ?? [], id: \.self) { row in Text("Section #\(section) - Row #\(row)") .onAppear { // Load more data when row appears loadMoreInner(section: section) } } } } .onAppear { // Load more sections when section appears loadMoreOuter() } } } } } } Enable Accessibility Inspector in iOS Simulator: Xcode → Open Developer Tool → Accessibility Inspector Select your running simulator Enable Inspection mode (eye icon) Navigate to the view and start scrolling Result: The application hangs and becomes unresponsive within a few seconds of scrolling Expected Behavior The application should remain responsive when Accessibility Inspector or VoiceOver is enabled, allowing users to scroll through nested lazy containers without freezing. Actual Behavior The application freezes/hangs completely CPU usage may spike The app must be force-quit to recover The hang occurs consistently and is reproducible Workaround 1: Replace inner LazyVStack with VStack LazyVStack { ForEach(...) { section in VStack { // ← Changed from LazyVStack ForEach(...) { row in ... } } } } Workaround 2: Embed in TabView TabView { NavigationStack { NestedLazyVStackView() // ← Same nested structure, but no hang } .tabItem { ... } } Interestingly, wrapping the entire navigation stack in a TabView prevents the hang entirely, even with the nested LazyVStack structure intact. Questions for Apple Is there a known issue with nested LazyVStack containers and accessibility traversal? Why does wrapping the view in a TabView prevent the hang? Are there recommended patterns for using nested lazy containers with accessibility support? Is this a timing issue, a deadlock, or an infinite loop in the accessibility system? Why that happens? Reproduction Project A complete, minimal reproduction project is available at: https://github.com/pendo-io/SwiftUI_Hang_Reproduction
Replies
8
Boosts
0
Views
594
Activity
2d
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
306
Activity
2d
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
30
Activity
2d
Are there any ways to prevent app record/capture on macOS
I'm looking for a way to prevent my app from displaying in screenshots and screen recordings. There appears to be plenty of options for UIKit/iOS but nothing I can find for macOS. userDidTakeScreenshotNotification @Environment(.sceneCaptureState) private var captureState Obviously it's possible though as I remember back in the day you couldn't take screenshots of the DVD Player etc.
Replies
0
Boosts
0
Views
38
Activity
2d
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
152
Activity
3d
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
39
Activity
3d
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
693
Activity
3d
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
31
Activity
3d
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
774
Activity
3d
Snippet Views don't render consistently, width not always respected
I've created a Snippet for my iOS app which I want to be able to run from the LockScreen via a Shortcuts widget. All works fine except when I run the shortcut and the App Snippet appears, it doesn't always render the SwiftUI view in the same way. Sometimes the width boundaries are respected and sometimes not. I've tested this on iOS 26.1 and iOS 26.2 beta 3 I think this is a bug but it would be great if anyone could see what I might be doing wrong if it's not. Incase it is a bug I've filed a feedback (FB21076429) and I've created a stripped down sample project showing the issue and added screenshots showing the issue. Basic code to reproduce issue: // Intent.swift // SnippetBug import AppIntents import Foundation import SwiftUI struct SnippetEntryIntent: AppIntent { static let title: LocalizedStringResource = "Open Snippet" static let description = IntentDescription("Shows a snippet.") // Don’t open the app – stay in the snippet surface. static let openAppWhenRun: Bool = false func perform() async throws -> some ShowsSnippetIntent { .result(snippetIntent: TestSnippetIntent()) } } struct TestSnippetIntent: SnippetIntent { static let title: LocalizedStringResource = "Snippet Intent" static let description = IntentDescription("Action from snippet.") @MainActor func perform() async throws -> some IntentResult & ShowsSnippetView { .result(view: SnippetView(model: SnippetModel.shared)) } } @MainActor final class SnippetModel { static let shared = SnippetModel() private init() { } } struct SnippetView: View { let model: SnippetModel var body: some View { HStack { Text("Test Snippet with information") Spacer() Image(systemName: "heart") }.font(.headline) } } struct Shortcuts: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: SnippetEntryIntent(), phrases: [ "Snippet for \(.applicationName)", "Test Snippet \(.applicationName)" ], shortTitle: "Snippet", systemImageName: "barcode" ) } } You also need these lines in your main App entry point: import AppIntents @main struct SnippetBugApp: App { init() { let model = SnippetModel.shared AppDependencyManager.shared.add(dependency: model) } var body: some Scene { WindowGroup { ContentView() } } } This is correct This is incorrect
Replies
2
Boosts
1
Views
327
Activity
1w
VideoPlayer crashes on Archive build
I have found that following code runs without issue from Xcode, either in Debug or Release mode, yet crashes when running from the binary produced by archiving - i.e. what will be sent to the app store. import SwiftUI import AVKit @main struct tcApp: App { var body: some Scene { WindowGroup { VideoPlayer(player: nil) } } } This is the most stripped down code that shows the issue. One can try and point the VideoPlayer at a file and the same issue will occur. I've attached the crash log: Crash log Please note that this was seen with Xcode 26.2 and MacOS 26.2.
Replies
2
Boosts
0
Views
814
Activity
1w
Different keyboards show up for KeyboardType .decimalPad
Environment: iOS 26; iPad Mini/Air/Pro Problem: In a TextField, I am using a keyboard with the type .decimalPad. When I initially tap into the TextField, the "popover" keyboard (i.e. the decimalPad) shows up and focusses the TextField. However, when I click outside the TextField (to dismiss the keyboard), the TextField is still focussed (the keyboard was dismissed though). When reentering in the TextField, another keyboard (from the bottom of the screen) appears (most likely .numeric). Does anybody know how to solve this? What I already tried: I tried listening to the dismissal of the keyboard to manually set the FocusState to nil. However, the dismissal of the "popover/decimal" keyboard is not recognized as such a dismissal. I also tried to build a custom component out of that, but then I lose the TextField behavior, conflicting with HIG.
Replies
2
Boosts
0
Views
160
Activity
1w
WindowGrop How to customize bending styles?
How should I set the window of WindowGrop to resemble a curved screen style?
Replies
3
Boosts
0
Views
753
Activity
1w
Delay when using ResultsObserver over @Query?
I was testing how to use ResultsObserver on a ViewModel in SwiftData. In Xcode 27, Developer v1, I have the following view import SwiftUI import SwiftData @Model class TaskItem { var name: String var priority: Int init(name: String, priority: Int) { self.name = name self.priority = priority } } @Observable @MainActor class RandomViewModel { let observer: ResultsObserver<TaskItem, Never> @ObservationIgnored private var token: ObservationTracking.Token? var tasks: FetchResultsCollection<TaskItem> { observer.results } init(context: ModelContext) { let descriptor = FetchDescriptor<TaskItem>( sortBy: [SortDescriptor(\.name, order: .reverse)] ) observer = try! ResultsObserver(fetchDescriptor: descriptor, modelContext: context) } } struct RandomView: View { @State var viewModel: RandomViewModel? @Environment(\.modelContext) private var modelContext var body: some View { VStack { if let viewModel { List(viewModel.tasks) { foo in Text(foo.name) } .toolbar { ToolbarItem(placement: .primaryAction) { Button("Add Task") { let task = TaskItem(name: "ZZ New Task \(viewModel.observer.results.count + 1)", priority: 2) print("add \(task.name)") modelContext.insert(task) } } } } else { Text("Hello, World!") } } .task { if viewModel == nil { viewModel = RandomViewModel(context: modelContext) } } } } func testContainer() -> ModelContainer { let schema = Schema([ Item.self, TaskItem.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true) let container = try! ModelContainer(for: schema, configurations: [modelConfiguration]) let modelContext = container.mainContext for i in 1...20 { let item = TaskItem(name: "Sample Task \(i)", priority: Int.random(in: 1...5)) modelContext.insert(item) } return container } #Preview { NavigationStack { RandomView() } .modelContainer(testContainer()) } When I run the Preview or the simulator, the UI takes a while to actually load and show the results. If I try a version using @Query this doesn't happen import SwiftData import SwiftUI struct RandomQueryView: View { @Environment(\.modelContext) private var modelContext @Query(sort: [SortDescriptor(\TaskItem.name, order: .reverse)]) private var tasks: [TaskItem] var body: some View { List(tasks) { task in Text(task.name) } .toolbar { ToolbarItem(placement: .primaryAction) { Button("Add Task") { let task = TaskItem(name: "ZZ New Task \(tasks.count + 1)", priority: 2) print("add \(task.name)") modelContext.insert(task) } } } } } #Preview { NavigationStack { RandomQueryView() } .modelContainer(testContainer()) } Is this a bug in SwiftData ResultsObserver? or am I using it wrong? I add a recording of my simulator showing the difference
Replies
1
Boosts
0
Views
120
Activity
1w