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

NavigationStack path is being reset in NavigationSplitView details columns
I'm building a SwiftUI app for iPad using a NavigationSplitView as the navigation root. Below is a simplified version of the app's navigation. There are a Home Page and a Settings Page, each with its own NavigationStack. The page that appears in the detail column depends on the sidebar's selection value. The issue I'm facing is that when I navigate deeply into the Home Page's NavigationStack (e.g., to a Home Page Child view), switch to the Settings Page, and then switch back to the Home Page, the Home Page's navigation path has been reset to [] and the previous state is lost. The same issue occurs if I navigate deeply into the Settings Page (e.g., to a Settings Page Child view), switch to the Home Page, and then return to the Settings Page: the navigation state for the Settings Page is lost, and it reverts to the root of the NavigationStack. Why is this happening and how can I fix it so that switching pages in the sidebar doesn't reset the NavigationStack of each individual page in the detail column? Thank you. struct ContentView: View { @State var selection: String? @State var firstPath = [String]() @State var secondPath = [String]() var body: some View { NavigationSplitView { List(selection: $selection) { Text("Home") .tag("home") Text("Settings") .tag("settings") } } detail: { if selection == "home" { HomePage(path: $firstPath) } else { SettingsPage(path: $secondPath) } } } } struct HomePage: View { @Binding var path: [String] var body: some View { NavigationStack(path: $path) { NavigationLink("Home Page", value: "Home") .navigationDestination(for: String.self) { _ in Text("Home Page Child") } } } } struct SettingsPage: View { @Binding var path: [String] var body: some View { NavigationStack(path: $path) { NavigationLink("Settings Page", value: "Settings") .navigationDestination(for: String.self) { _ in Text("Settings Page Child") } } } } #Preview { ContentView() }
0
0
226
1w
Textfield not updating integer with optional value
I am trying to get integer input by using textfield. However, I noticed that if I changed the binding variable as optional with an initial value of null, the textfield would not work. I would like to keep it as null initially because I want the placeholder to show text before the input, and if the int variable starts with any valid value, the text would not be shown. Is there a way to fix things here? struct TextFieldNumberInputView: View {     @Binding var intVariable: Int?     @State var isEditing: Bool = false     @State var placeholderText: String     @State var number: Int = 0          var body: some View {         VStack(alignment: .leading, spacing: 2){             TextField(placeholderText, value: $number, formatter: NumberFormatter()){             }             .textFieldStyle(InputTextFieldStyle())             .keyboardType(.numberPad)             .onReceive(Just(number)) {_ in                 print("number pad being editing")                 if isEditing == false && intVariable != nil {                                         isEditing = true                     print("number is being edited")                 } else if isEditing == true && intVariable != nil{                     isEditing = false                 }             }                          Text(placeholderText)                 .font(.caption2)                 .foregroundColor(isEditing ? Color(.systemGray3):Color.clear)                 .padding(.horizontal)                 .padding(.horizontal, 12)                  }.onTapGesture {             print("number pad being tapped, intVariable \(intVariable), \(number)")                          if number != nil {                 print("checking number")                 UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to:nil, from:nil, for:nil)             }                      }     }      }
2
0
748
1w
Charts SectorMark causing app to crash
Anytime I have 1 item, then add another, the app crashes with the following error: Swift/IntegerTypes.swift:8835: Fatal error: Double value cannot be converted to Int because it is either infinite or NaN I'm not working with Int values though, so I'm not sure why this is happening. It's also not point me towards any specific line. I've printed out all of the values being used for the chart and none of them are showing as infinite or NaN. The data being used is created in a View. @State private var pieChartData: [PieChartDataPoint] = [] Then in the onAppear and onChange its gets loaded using the following function: func getPieChartDataPoints() -> [PieChartDataPoint] { self.map({ PieChartDataPoint(label: $0.name, value: $0.monthlyAmount()) }) } That's an extension on a SwiftData model type I have called Recurring. @Model final class Recurring { var id = UUID() enum Kind: String, CaseIterable, Codable { case income = "Income" case bill = "Bill" func plural() -> String { switch self { case .income: "Income" case .bill: "Bills" } } } enum Frequency: String, CaseIterable, Codable, Identifiable { var id: Frequency { self } case weekly = "Weekly" case biweekly = "Biweekly" case monthly = "Monthly" case quarterly = "Quarterly" case annually = "Annually" } var name: String = "" var kind: Kind = Kind.income var frequency: Frequency = Frequency.biweekly var amount: Double = 0 init(name: String, kind: Kind, frequency: Frequency, amount: Double) { self.name = name self.kind = kind self.frequency = frequency self.amount = amount } func amount(from cycle: Cycle) -> Double { switch cycle { case .weekly: monthlyAmount() * 12 / 52 case .biweekly: monthlyAmount() * 12 / 26 case .monthly: monthlyAmount() } } func monthlyAmount() -> Double { switch frequency { case .weekly: amount * 52 / 12 case .biweekly: amount * 26 / 12 case .monthly: amount case .quarterly: amount * 4 / 12 case .annually: amount / 12 } } } Here is the DataPoint structure. struct PieChartDataPoint: Identifiable, Equatable { var id = UUID() var label: String var value: Double } Finally here is the chart. Chart(sorted, content: { dataPoint in SectorMark( angle: .value(dataPoint.label, getValue(from: dataPoint)), innerRadius: 50, angularInset: 5 ) .foregroundStyle(by: .value("Label", dataPoint.label)) .cornerRadius(10) .opacity(getSectorMarkOpacity(for: dataPoint)) }) .scaledToFill() .chartLegend(.hidden) .chartAngleSelection(value: $chartSelection) .onChange(of: chartSelection, checkSelection) For testing purposes, I have removed all of the modifiers and only had a simple SectorMark in the Chart, however, that was still crashing. Does anyone know why this is happening?
1
0
54
1w
UtilityWindow can't read @FocusedValue of main scene
According to the UtilityWindow documentation: • They receive FocusedValues from the focused main scene in an application, similar to commands in the main menu, which can be used to display information on the active content as the user focuses on different scenes. This makes me think that any UtilityWindow, even across Scenes, should always receive @FocusedValues from the currently focused window of any scene. However, the following code doesn't quite work: @Observable class Info: Identifiable { let id = UUID() } struct ExampleApp: App { var body: some Scene { WindowGroup { ContentView() // Inside, it uses .focusedSceneValue(info) } UtilityWindow("Test") { UtilityWindowContent() } } } struct UtilityWindowContent: View { @FocusedValue(Info.self) var info var body: some View { Text(info?.id ?? "<nil>") // This always shows "<nil>" } } Here's some annotated screenshots of what's happening in a project: Menu bar commands do work with the same setup: As a workaround, attempting to use @FocusedValue in the App struct works, but as a result, the value appears to instantiate multiple times in the background, and they re-instantiate with every focus change. The @FocusedValue variable gets the correct instance, but it's needlessly initializing others in the background. This is on macOS 26.0 Tahoe Beta 8 (25A5349a).
0
0
94
1w
SwiftUI drag & drop: reliable cancellation
Summary In a SwiftUI drag-and-drop flow, the only robust way I’ve found to detect cancellation (user drops outside any destination) is to rely on the NSItemProvider created in .onDrag and run cleanup when it’s deallocated, via a custom onEnded callback tied to its lifecycle. On iOS 26, the provider appears to be deallocated immediately after .onDrag returns (unless I keep a strong reference), so a deinit/onEnded-based cancel hook fires right away and no longer reflects the true end of the drag session. I’d like to know: 1. Is there a supported, reliable way to detect when a drag ends outside any drop target so I can cancel and restore the source row? 2. Is the iOS 26 NSItemProvider deallocation timing a bug/regression or intended behavior? Minimal SwiftUI Repro This example shows: • creating a custom NSItemProvider subclass with an onEnded closure • retaining it to avoid immediate dealloc (behavior change on iOS 26) • using performDrop to mark the drag as finished import SwiftUI import UniformTypeIdentifiers final class DragProvider: NSItemProvider { var onEnded: (() -> Void)? deinit { // Historically: called when the system drag session ended (drop or cancel). // On iOS 26: can fire immediately after .onDrag returns unless the provider is retained. onEnded?() } } struct ContentView: View { struct Item: Identifiable, Equatable { let id = UUID(); let title: String } @State private var pool: [Item] = (1...4).map { .init(title: "Option \($0)") } @State private var picked: [Item] = [] @State private var dragged: Item? @State private var dropFinished: Bool = true @State private var activeProvider: DragProvider? // Retain to avoid immediate dealloc private let dragType: UTType = .plainText var body: some View { HStack(spacing: 24) { // Destination list (accepts drops) VStack(alignment: .leading, spacing: 8) { Text("Picked").bold() VStack(spacing: 8) { ForEach(picked) { item in row(item) } } .padding() .background(RoundedRectangle(cornerRadius: 8).strokeBorder(.quaternary)) .onDrop(of: [dragType], delegate: Dropper( picked: $picked, pool: $pool, dragged: $dragged, dropFinished: $dropFinished, activeProvider: $activeProvider )) } .frame(maxWidth: .infinity, alignment: .topLeading) // Source list (draggable) VStack(alignment: .leading, spacing: 8) { Text("Pool").bold() VStack(spacing: 8) { ForEach(pool) { item in row(item) .onDrag { startDrag(item) return makeProvider(for: item) } preview: { row(item).opacity(0.9).frame(width: 200, height: 44) } .overlay( RoundedRectangle(cornerRadius: 8) .fill(item == dragged ? Color(.systemBackground) : .clear) // keep space ) } } .padding() .background(RoundedRectangle(cornerRadius: 8).strokeBorder(.quaternary)) } .frame(maxWidth: .infinity, alignment: .topLeading) } .padding() } private func row(_ item: Item) -> some View { RoundedRectangle(cornerRadius: 8) .strokeBorder(.secondary) .frame(height: 44) .overlay( HStack { Text(item.title); Spacer(); Image(systemName: "line.3.horizontal") } .padding(.horizontal, 12) ) } // MARK: Drag setup private func startDrag(_ item: Item) { dragged = item dropFinished = false } private func makeProvider(for item: Item) -> NSItemProvider { let provider = DragProvider(object: item.id.uuidString as NSString) // NOTE: If we DO NOT retain this provider on iOS 26, // its deinit can run immediately (onEnded fires too early). activeProvider = provider provider.onEnded = { [weak self] in // Intended: run when system drag session ends (drop or cancel). // Observed on iOS 26: may run too early unless retained; // if retained, we lose a reliable "session ended" signal here. DispatchQueue.main.async { guard let self else { return } if let d = self.dragged, self.dropFinished == false { // Treat as cancel: restore the source item if !self.pool.contains(d) { self.pool.append(d) } self.picked.removeAll { $0 == d } } self.dragged = nil self.dropFinished = true self.activeProvider = nil } } return provider } // MARK: DropDelegate private struct Dropper: DropDelegate { @Binding var picked: [Item] @Binding var pool: [Item] @Binding var dragged: Item? @Binding var dropFinished: Bool @Binding var activeProvider: DragProvider? func validateDrop(info: DropInfo) -> Bool { dragged != nil } func performDrop(info: DropInfo) -> Bool { guard let item = dragged else { return false } if let idx = pool.firstIndex(of: item) { pool.remove(at: idx) } picked.append(item) // Mark drag as finished so provider.onEnded won’t treat it as cancel dropFinished = true dragged = nil activeProvider = nil return true } } } Questions Is there a documented, source-side callback (or best practice) to know the drag session ended without any performDrop so we can cancel and restore the item? Has the NSItemProvider deallocation timing (for the object returned from .onDrag) changed intentionally on iOS 26? If so, what’s the recommended replacement signal? Is there a SwiftUI-native event to observe the end of a drag session that doesn’t depend on the provider’s lifecycle?
0
1
83
1w
PasteButton asks for permissions every time
Hi, i'm using the PasteButton component to paste content from clipboard. On the docs it says that the PasteButton will handle internally permissions and will not present the prompt. But in my case seems to be not true. I removed all the occurrencies of UIPasteboard.general.string since i read that this will cause the prompt to appear. Also as you can see on the code below i'm not doing fancy or weird things, even with the base component this behaviour is still there. PasteButton(payloadType: String.self) { strings in if let first = strings.first { print("clipboard text: \(first)") } } I can see other apps using this paste button without asking for permissions every time, but i cannot see any issue in my code.
0
0
14
1w
SwiftUI app crash with __swift_instantiateConcreteTypeFromMangledName
Hello, I am experiencing a crash in a SwiftUI app. It happens when I place multiple views inside a ScrollView. The crash occurs only on a physical device (it does not reproduce in the Simulator). It happens during runtime, seemingly while SwiftUI is updating or laying out the view hierarchy. I have not been able to determine the exact cause. I am attaching a text file with the entire backtrace from LLDB. swiftui_crash_backtrace Is this a known SwiftUI issue? Any recommendations on how to further investigate or work around it? Any help or suggestions would be appreciated. Xcode 16.3 / iOS 18.6.2 Thank you!
1
0
82
1w
Keyboard dismissal not animated
Hello, I’ve encountered what seems to be a bug with the keyboard dismissal animation on iOS 26.0 Beta (25A5349a), Xcode Version 26.0 beta 5 (17A5295f). When dismissing the keyboard from a SwiftUI TextField using @FocusState, the keyboard does not animate downward as expected. Instead, it instantly disappears, which feels jarring and inconsistent with system behavior. I am attaching a short video demonstrating the issue. Below is the minimal reproducible code sample: // // ContentView.swift // TestingKeyboardDismissal // // Created by Sasha Morozov on 27/08/25. // import SwiftUI struct ContentView: View { @State private var text: String = "" @FocusState private var isFocused: Bool var body: some View { ZStack { Color.clear.ignoresSafeArea() VStack(spacing: 20) { TextField("Enter text here...", text: $text) .textFieldStyle(.roundedBorder) .focused($isFocused) .padding(.horizontal) HStack { Button("Focus") { isFocused = true } .buttonStyle(.borderedProminent) Button("Unfocus") { isFocused = false } .buttonStyle(.bordered) } } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .padding() } .ignoresSafeArea(.keyboard, edges: .bottom) } } #Preview { ContentView() } Steps to reproduce: Run** the app on iOS 26.0 beta 5 (17A5295f). Tap Focus → keyboard appears as expected. Tap Unfocus → keyboard disappears instantly without the usual slide-down animation. Expected result: Keyboard should animate smoothly downwards when dismissed. Actual result: Keyboard instantly vanishes without animation. p.s. we should be really able to upload videos here for demostration
2
1
110
1w
Illegible navigation title when presenting Map view
When building with the iOS 26 SDK (currently beta 4), the navigation title is often illegible when rendering a Map view. For example, note how the title "Choose Location" is obscured by the map's text ("South America") in the screenshot below: This screenshot is the result of the following view code: import MapKit import SwiftUI struct Demo: View { var body: some View { NavigationStack { Map() .navigationTitle(Text("Choose Location")) .navigationBarTitleDisplayMode(.inline) } } } I tried using the scrollEdgeEffectStyle(_:for:) modifier to apply a scroll edge effect to the top of the screen, in hopes of making the title legible, but that doesn't seem to have any effect. Specifically, the following code seems to produce the exact same result shown in the screenshot above. import MapKit import SwiftUI struct Demo: View { var body: some View { NavigationStack { Map() .scrollEdgeEffectStyle(.hard, for: .top) // ⬅️ no apparent effect .navigationTitle(Text("Choose Location")) .navigationBarTitleDisplayMode(.inline) } } } Is there a recommended way to resolve this issue so that the navigation title is always readable?
4
3
163
1w
iOS 26 Beta bug - keyboard toolbar with bottom safe area inset
Hello! I have experienced a weird bug in iOS 26 Beta (8) and previous beta versions. The safe area inset is not correctly aligned with the keyboard toolbar on real devices and simulators. When you focus a new textfield the bottom safe area is correctly placed aligned the keyboard toolbar. On real devices the safe area inset view is covered slightly by the keyboard toolbar, which is even worse than on the simulator. Here's a clip from a simulator: Here's the code that reproduced the bug I experienced in our app. #Preview { NavigationStack { ScrollView { TextField("", text: .constant("")) .padding() .background(Color.secondary) TextField("", text: .constant("")) .padding() .background(Color.green) } .padding() .safeAreaInset(edge: .bottom, content: { Color.red .frame(maxWidth: .infinity) .frame(height: 40) }) .toolbar { ToolbarItem(placement: .keyboard) { Button {} label: { Text("test") } } } } }
0
6
236
1w
Borderless NavigationLink broken in tvOS 26
NavigationLinks do not display correctly in tvOS 26. When using a Button, the correct behavior of vertically placing an Image or AsyncImage above one or two Text fields occurs. However, when using NavigationLink the image and text(s) are laid out horizontally. Attempting to fix this using a VStack prevents the text from sliding down as the NavigationLink receives focus. Using the hoverEffect modifier does not help. Using a Button (correct behavior): Using a NavigationLink without VStack: Using a NavigationLink with VStack:
3
1
77
1w
`onTapGesture` not triggered on `Map` views
When building with iOS 26 SDK beta 5 (23A5308f), onTapGesture is no longer being triggered on Map views. This appears to be a regression in beta 5 specifically, as this issue was not present in beta 4. How to reproduce Code The following code demonstrates the issue, as seen in the videos below. import MapKit import SwiftUI struct ContentView: View { @State private var location = CGPoint.zero var body: some View { Map() .onTapGesture { location in self.location = location } .safeAreaInset(edge: .bottom) { VStack(alignment: .center) { Text("iOS \(UIDevice.current.systemVersion)") .font(.largeTitle) Text("Tapped Location") Text("\(location.x), \(location.y)") } .frame(maxWidth: .infinity, alignment: .center) .background(.background) } } } Demo The gifs below show the behavior in iOS 18.5 (in which the tap gestures are recognized and tapped coordinate is displayed in the safe area inset) and iOS 26 beta 5 (in which the tap gestures have no effect): iOS 18 iOS 26 Next steps? Is there a recommended workaround for this issue?
15
3
310
1w
Different toolbar item placement for iPhone vs iPad
On iPhone, I would like to have a more button at the top right of the navigation bar, a search field in the bottom toolbar, and a plus button to the right of the search field. I've achieved this via the code below. But on iPad they should be in the navigation bar at the trailing edge from left to right: plus, more, search field. Just like the Shortcuts app, if there's not enough horizontal space, the search field should collapse into a button, and with even smaller space the search bar should become full-width under the navigation bar. Right now on iPad the search bar is full width under the navigation bar, more at top right, plus at bottom middle, no matter how big the window is. How can I achieve that? Any way to specify them for the system to more automatically do the right thing, or would I need to check specifically for iPhone vs iPad UIDevice to change the code? struct ContentView: View { @State private var searchText = "" var body: some View { NavigationStack { VStack { Text("Hello, world!") } .navigationTitle("Test App") .searchable(text: $searchText) .toolbar { ToolbarItem { Menu { //... } label: { Label("More", systemImage: "ellipsis") } } DefaultToolbarItem(kind: .search, placement: .bottomBar) ToolbarSpacer(.fixed, placement: .bottomBar) ToolbarItem(placement: .bottomBar) { Button { print("Add tapped") } label: { Label("Add", systemImage: "plus") } } } } } }
3
0
97
1w
Should SwiftUI view models in Swift 6 be both @Observable and @MainActor?
Hi, In the WWDC25 session Elevate an app with Swift concurrency (timestamps: 8:04 and later), the StickerViewModel is shown annotated with @Observable but not @MainActor. The narration mentions that updates happen on the main thread, but that guarantee is left implicit in the calling code. In Swift 6, though, one of the major benefits is stronger compiler enforcement against data races and isolation rules. If a view model were also annotated with @MainActor, then the compiler could enforce that observable state is only updated on the main actor, preventing accidental background mutations or updates that can cause data races between nonisolated and main actor-isolated uses. Since @Observable already signals that state changes are intended to be observed (and in practice, usually by views), it seems natural that such types should also be main-actor isolated. Otherwise, we’re left with an implicit expectation that updates will always come from the main thread, but without the compiler’s help in enforcing that rule. This also ties into the concept of local reasoning that was emphasized in other Swift 6 talks (e.g. Beyond the basics of structured concurrency). With @MainActor, I can look at a view model and immediately know that all of its state is main-actor isolated. With only @Observable, that guarantee is left out, which feels like it weakens the clarity that Swift 6 is trying to promote. Would it be considered a best practice in Swift 6 to use both @Observable and @MainActor for UI-facing view models? Or is the intention that SwiftUI developers should rely on calling context to ensure main-thread updates, even if that means the compiler cannot enforce isolation? Thanks!
6
0
209
1w
Is realtime multidevice persistence possible using SwiftData?
I really enjoyed using SwiftData for persistence until I found out that the CloudKit integration ensures changes are only eventually consistent, and that changes can propagate to other devices after as long as minutes, making it useless for any feature that involves handoff between devices. Devastating news but I guess it’s on me for nrtfm. I may try my hand at a custom model context DataStore integrating Powersync, but that’s a whole trip and before I embark on it I was wondering if anyone had suggestions for resolving this problem in a simple and elegant manager that allows me to keep as much of the machinery within Apple’s ecosystem as possible, while ensure reliable “live” updates to SwiftData stores on all eligible devices.
2
0
165
1w
ManipulationComponent + Warning messages in RealityView
Hi guys! I wanted to study this new ManipulationComponent(), but I keep getting a warning that I don’t understand, even in a very simple scenario. i don't have any collisions just binding the Manipulation the warning message is : ** Entity returned from EntityWrapper.makeEntity(context:) was already parented to another entity. This is not supported and may lead to unexpected behavior. SwiftUI adds entities to internally-managed entity hierarchies.** RealityView { content, attachments in if let loadedModel = try? await Entity(named: "cloud_glb", in: realityKitContentBundle) { content.add(loadedModel) loadedModel.components.set(ManipulationComponent()) } Thanks !
1
0
87
1w
iOS26: Programmatically Triggering the Format Sheet for AttributedString?
I've been exploring the resources from WWDC25 Session 280: "Code-along: Cook up a rich text experience in SwiftUI with AttributedString" and the SwiftUI documentation on "Building rich SwiftUI text experiences." After spending some time experimenting and trying to implement these features with these APIs on iOS26 , I’ve run into a specific question. Is there a way to programmatically trigger the Format Sheet directly—for example, from a custom button—rather than requiring the user to go through the multi-step process of selecting text, opening the context menu, tapping "Format," and then selecting "More"? I’d like to provide a more streamlined editing experience in my app. Any guidance would be greatly appreciated!
0
0
22
1w
How to Detect Key + Modifier Combinations at Runtime in SwiftUI on iOS (Without Using .keyboardShortcut)?
In my SwiftUI iOS app, I need to detect which key (and modifier flags – Command, Option, Shift, Control) a user presses, but I don't want to pre-register them using .keyboardShortcut(_:modifiers:). My use case is that keyboard shortcuts are user-configurable, so I need to capture the actual key + modifier combination dynamically at runtime and perform the appropriate action based on the user’s settings. Questions: What is the recommended way to detect arbitrary key + modifier combinations in SwiftUI on iOS? Is there a SwiftUI-native solution for this, or should I rely on UIPressesEvent and wrap it with UIViewControllerRepresentable? If UIKit bridging is necessary, what is the cleanest pattern for integrating this with SwiftUI views (e.g., Buttons)? Any official guidance or best practices would be greatly appreciated!
1
0
122
1w