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

A Summary of the WWDC25 Group Lab - SwiftUI
At WWDC25 we launched a new type of Lab event for the developer community - Group Labs. A Group Lab is a panel Q&A designed for a large audience of developers. Group Labs are a unique opportunity for the community to submit questions directly to a panel of Apple engineers and designers. Here are the highlights from the WWDC25 Group Lab for SwiftUI. What's your favorite new feature introduced to SwiftUI this year? The new rich text editor, a collaborative effort across multiple Apple teams. The safe area bar, simplifying the management of scroll view insets, safe areas, and overlays. NavigationLink indicator visibility control, a highly requested feature now available and back-deployed. Performance improvements to existing components (lists, scroll views, etc.) that come "for free" without requiring API adoption. Regarding performance profiling, it's recommended to use the new SwiftUI Instruments tool when you have a good understanding of your code and notice a performance drop after a specific change. This helps build a mental map between your code and the profiler's output. The "cause-and-effect graph" in the tool is particularly useful for identifying what's triggering expensive view updates, even if the issue isn't immediately apparent in your own code. My app is primarily UIKit-based, but I'm interested in adopting some newer SwiftUI-only scene types like MenuBarExtra or using SwiftUI-exclusive features. Is there a better way to bridge these worlds now? Yes, "scene bridging" makes it possible to use SwiftUI scenes from UIKit or AppKit lifecycle apps. This allows you to display purely SwiftUI scenes from your existing UIKit/AppKit code. Furthermore, you can use SwiftUI scene-specific modifiers to affect those scenes. Scene bridging is a great way to introduce SwiftUI into your apps. This also allows UIKit apps brought to Vision OS to integrate volumes and immersive spaces. It's also a great way to customize your experience with Assistive Access API. Can you please share any bad practices we should avoid when integrating Liquid Glass in our SwiftUI Apps? Avoid these common mistakes when integrating liquid glass: Overlapping Glass: Don't overlap liquid glass elements, as this can create visual artifacts. Scrolling Content Collisions: Be cautious when using liquid glass within scrolling content to prevent collisions with toolbar and navigation bar glass. Unnecessary Tinting: Resist the urge to tint the glass for branding or other purposes. Liquid glass should primarily be used to draw attention and convey meaning. Improper Grouping: Use the GlassEffectContainer to group related glass elements. This helps the system optimize rendering by limiting the search area for glass interactions. Navigation Bar Tinting: Avoid tinting navigation bars for branding, as this conflicts with the liquid glass effect. Instead, move branding colors into the content of the scroll view. This allows the color to be visible behind the glass at the top of the view, but it moves out of the way as the user scrolls, allowing the controls to revert to their standard monochrome style for better readability. Thanks for improving the performance of SwiftUI List this year. How about LazyVStack in ScrollView? Does it now also reuse the views inside the stack? Are there any best practices for improving the performance when using LazyVStack with large number of items? SwiftUI has improved scroll performance, including idle prefetching. When using LazyVStack with a large number of items, ensure your ForEach returns a static number of views. If you're returning multiple views within the ForEach, wrap them in a VStack to signal to SwiftUI that it's a single row, allowing for optimizations. Reuse is handled as an implementation detail within SwiftUI. Use the performance instrument to identify expensive views and determine how to optimize your app. If you encounter performance issues or hitches in scrolling, use the new SwiftUI Instruments tool to diagnose the problem. Implementing the new iOS 26 tab bar seems to have very low contrast when darker content is underneath, is there anything we should be doing to increase the contrast for tab bars? The new design is still in beta. If you're experiencing low contrast issues, especially with darker content underneath, please file feedback. It's generally not recommended to modify standard system components. As all apps on the platform are adopting liquid glass, feedback is crucial for tuning the experience based on a wider range of apps. Early feedback, especially regarding contrast and accessibility, is valuable for improving the system for all users. If I’m starting a new multi-platform app (iOS/iPadOS/macOS) that will heavily depend on UIKit/AppKit for the core structure and components (split, collection, table, and outline views), should I still use SwiftUI to manage the app lifecycle? Why? Even if your new multi-platform app heavily relies on UIKit/AppKit for core structure and components, it's generally recommended to still use SwiftUI to manage the app lifecycle. This sets you up for easier integration of SwiftUI components in the future and allows you to quickly adopt new SwiftUI features. Interoperability between SwiftUI and UIKit/AppKit is a core principle, with APIs to facilitate going back and forth between the two frameworks. Scene bridging allows you to bring existing SwiftUI scenes into apps that use a UIKit lifecycle, or vice versa. Think of it not as a binary choice, but as a mix of whatever you need. I’d love to know more about the matchedTransitionSource API you’ve added - is it a native way to have elements morph from a VStack to a sheet for example? What is the use case for it? The matchedTransitionSource API helps connect different views during transitions, such as when presenting popovers or other presentations from toolbar items. It's a way to link the user interaction to the presented content. For example, it can be used to visually connect an element in a VStack to a sheet. It can also be used to create a zoom effect where an element appears to enlarge, and these transitions are fully interactive, allowing users to swipe. It creates a nice, polished experience for the user. Support for this API has been added to toolbar items this year, and it was already available for standard views.
Topic: UI Frameworks SubTopic: SwiftUI
1
0
1k
Jun ’25
MacCatalyst and the User's Documents Folder
I have a SwiftUI-based universal app which creates a file that it stores in documentsDirectory. On iOS/iPadOS, this file is stored in the application's Documents directory and is accessible via the Files app. On MacCatalyst, this operation does the same thing — it creates the file and stores it in ~/Library/Containers/<app directory>/Data/Documents. However what I want is for the document to be stored in ~/Documents, so that it is easily accessible to the user. How can I do that? I'd like it to occur without (for example) having to show a SaveFile panel...
4
0
295
18h
On macOS, how do you place a toolbar item on the trailing edge of the window's toolbar when an Inspector view is open?
Using SwiftUI on macOS, how can I add a toolbar item on the right-most (trailing) edge of the window's toolbar when an Inspector is used? At the moment, the toolbar items are all left-of (leading) the split view tracking separator. I want the inspector toolbar item to be placed similar to where Xcode's Inspector toolbar item is placed: always as far right (trailing) as possible. NavigationSplitView { // ... snip } detail: { // ... snip } .inspector(isPresented: $isInspectorPresented) { InspectorContentView() } .toolbar { // What is the correct placement value here? ToolbarItem(placement: .primaryAction) { Button { isInspectorPresented.toggle() } label: { Label("Toggle Inspector", systemImage: "sidebar.trailing") } } } See the attached screenshot. When the InspectorView is toggled open, the toolbar item tracks leading the split view tracking separator, which is not consistent with how Xcode works.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
5
0
209
1d
AppIntents default value
Hi, I have created an AppIntent in which there is a parameter called price, I have set the default value as 0. @Parameter(title: "Price", default: 0) var price: Int Problem When the shortcut is run this parameter is skipped Aim I still want to price to be asked however it needs to be pre-filled with 0 Question What should I do that the shortcut can still ask the price but be pre-filled with 0?
0
0
32
1d
AppIntents
Overview I have a custom type Statistics that has 3 properties inside it I am trying to return this as part of the AppIntent's perforrm method struct Statistics { var countA: Int var countB: Int var countC: Int } I would like to implement the AppIntent to return Statistics as follows: func perform() async throws -> some IntentResult & ReturnsValue<Statistics> { ... ... } Problem It doesn't make much sense to make Statistics as an AppEntity as this is only computed as a result. Statistics doesn't exist as a persisted entity in the app. Questions How can I implement Statistics? Does it have to be AppEntity (I am trying to avoid this)? (defaultQuery would never be used.) What is the correct way tackle this?
0
0
44
1d
SwiftUI navigationTransition(.zoom) glitches during interactive swipe-back
Hi everyone 👋 I’m fairly new to iOS development and I’ve been stuck on a SwiftUI issue for a while now, so I’m hoping someone here can spot what I’m doing wrong. I’m using navigationTransition(.zoom) together with matchedTransitionSource to animate navigation between views. The UI consists of a grid of items (currently a LazyVGrid, though the issue seems unrelated to laziness). Tapping an item zooms it into its detail view, which is structurally the same view type and can contain further items. All good expect that interactive swipe-back sometimes causes the item to disappear from the grid once the parent view is revealed. This only happens when dismissing via the drag gesture; it does not occur when using the back button. I’ve attached a short demo showing the issue and the Swift file containing the relevant view code. Is there something obvious I’m doing wrong with navigationTransition / matchedTransitionSource, or is this a known limitation or bug with interactive swipe-back? Thanks in advance. import SwiftUI struct TestFileView: View { @Namespace private var ns: Namespace.ID let nodeName: String let children: [String] let pathPrefix: String private func transitionID(for childName: String) -> String { "Zoom-\(pathPrefix)->\(childName)" } private let columns = Array(repeating: GridItem(.flexible(), spacing: 12), count: 3) var body: some View { ScrollView { VStack(alignment: .leading, spacing: 12) { Text(nodeName) .font(.title.bold()) .padding(.bottom, 6) LazyVGrid(columns: columns, spacing: 12) { ForEach(children, id: \.self) { childName in let id = transitionID(for: childName) NavigationLink { TestFileView( nodeName: childName, children: childrenFor(childName), pathPrefix: "\(pathPrefix)/\(childName)" ) .navigationTransition(.zoom(sourceID: id, in: ns)) } label: { TestFileCard(title: childName) .matchedTransitionSource(id: id, in: ns) } .buttonStyle(.plain) } } } .padding() } } private func childrenFor(_ name: String) -> [String] { switch name { case "Lorem": return ["Ipsum", "Dolor", "Sit"] case "Ipsum": return ["Amet", "Consectetur"] case "Dolor": return ["Adipiscing", "Elit", "Sed"] case "Sit": return ["Do", "Eiusmod"] case "Amet": return ["Tempor", "Incididunt", "Labore"] case "Adipiscing": return ["Magna", "Aliqua"] case "Elit": return ["Ut", "Enim", "Minim"] case "Tempor": return ["Veniam", "Quis"] case "Magna": return ["Nostrud", "Exercitation"] default: return [] } } } struct TestFileCard: View { let title: String var body: some View { VStack(alignment: .leading, spacing: 8) { Image(systemName: "square.stack.3d.up") .symbolRenderingMode(.hierarchical) .font(.headline) Text(title) .font(.subheadline.weight(.semibold)) .lineLimit(2) .minimumScaleFactor(0.85) Spacer(minLength: 0) } .padding(12) .frame(maxWidth: .infinity, minHeight: 90, alignment: .topLeading) .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 14, style: .continuous)) } } private struct TestRoot: View { var body: some View { NavigationStack { TestFileView( nodeName: "Lorem", children: ["Ipsum", "Dolor", "Sit"], pathPrefix: "Lorem" ) } } } #Preview { TestRoot() }
Topic: UI Frameworks SubTopic: SwiftUI
2
0
205
2d
SwiftUI ScrollView blocked when content contains a drag gesture
I am porting my app to SwiftUI and I am hitting a wall when using ScrollView. In my application, I have nested scrollViews to represent a scheduler. outer vertical scroll view inner horizontal scroll view that allows to horizontally scroll multiple columns in the scheduler each column in the inner scroll view is a view that needs to allow for a drag to initiate the creation of a new appointment on macOS, I do a mouse-down drag, so it does not affect the scroll view and works fine on iOS, if I add a drag gesture to the column, it short circuits the scroll view and scrolling becomes disabled. To initiate the drag, there is a long-press, and that gesture is fine, only the subsequent drag gesture is problematic. I have attached URL to a test app. The UI allows you to toggle the drag gesture. Hopefully, someone can help to get it to work since I would eventually like to port the macOS target to Catalyst. Download Test App
Topic: UI Frameworks SubTopic: SwiftUI
1
0
121
2d
SwiftUI List cell reuse / view lifecycle behavior when scrolling
I’m trying to understand how SwiftUI List handles row lifecycle and reuse during scrolling. I have a list with around 60 card views; on initial load, only about 7 rows are created, but after scrolling to the bottom all rows appear to be created, and when scrolling back to the top I again observe multiple updates and apparent re-creation of rows. I confirmed this behavior using Instruments by profiling my app. Even though each row has a stable identifier, the row views still seem to be destroyed and recreated, which doesn’t resemble UIKit’s cell reuse model. I’d like clarity on how List uses identifiers internally, what actually gets reused versus recreated, and how developers should reason about performance and view lifetime in this case.
0
1
43
2d
help() view modifier
I have a bunch of Buttons with a .help(Text("Help text")) modifier, inside of a VStack which has its own .help() modifier describing the entire section. The VStack help shows up only when I hover over the buttons, and the Button help never shows at all. If I comment out the VStack help, the individual button helps show. How do I get both to show up properly? I want the VStack to show if I am in the roundedBorder, unless I am over a Button with its own .help modifier. import SwiftUI struct BugReport: View { @State private var testp1 = false @State private var testp2 = false var body: some View { VStack { Text("Hello, World!") Button("Test1") { testp1.toggle() } .help("Change the test1") Button("Test2") { testp2.toggle() } .help("Change the test2") } .help("Testing stuff") .roundedBorder(color: .black) } } #Preview { BugReport() }
Topic: UI Frameworks SubTopic: SwiftUI
3
0
307
3d
Slow rendering List backed by SwiftData @Query
Hello, I've a question about performance when trying to render lots of items coming from SwiftData via a @Query on a SwiftUI List. Here's my setup: // Item.swift: @Model final class Item: Identifiable { var timestamp: Date var isOptionA: Bool init() { self.timestamp = Date() self.isOptionA = Bool.random() } } // Menu.swift enum Menu: String, CaseIterable, Hashable, Identifiable { var id: String { rawValue } case optionA case optionB case all var predicate: Predicate<Item> { switch self { case .optionA: return #Predicate { $0.isOptionA } case .optionB: return #Predicate { !$0.isOptionA } case .all: return #Predicate { _ in true } } } } // SlowData.swift @main struct SlowDataApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([Item.self]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) return try! ModelContainer(for: schema, configurations: [modelConfiguration]) }() var body: some Scene { WindowGroup { ContentView() } .modelContainer(sharedModelContainer) } } // ContentView.swift struct ContentView: View { @Environment(\.modelContext) private var modelContext @State var selection: Menu? = .optionA var body: some View { NavigationSplitView { List(Menu.allCases, selection: $selection) { menu in Text(menu.rawValue).tag(menu) } } detail: { DemoListView(selectedMenu: $selection) }.onAppear { // Do this just once // (0..<15_000).forEach { index in // let item = Item() // modelContext.insert(item) // } } } } // DemoListView.swift struct DemoListView: View { @Binding var selectedMenu: Menu? @Query private var items: [Item] init(selectedMenu: Binding<Menu?>) { self._selectedMenu = selectedMenu self._items = Query(filter: selectedMenu.wrappedValue?.predicate, sort: \.timestamp) } var body: some View { // Option 1: touching `items` = slow! List(items) { item in Text(item.timestamp.description) } // Option 2: Not touching `items` = fast! // List { // Text("Not accessing `items` here") // } .navigationTitle(selectedMenu?.rawValue ?? "N/A") } } When I use Option 1 on DemoListView, there's a noticeable delay on the navigation. If I use Option 2, there's none. This happens both on Debug builds and Release builds, just FYI because on Xcode 16 Debug builds seem to be slower than expected: https://indieweb.social/@curtclifton/113273571392595819 I've profiled it and the SwiftData fetches seem blazing fast, the Hang occurs when accessing the items property from the List. Is there anything I'm overlooking or it's just as fast as it can be right now?
5
4
1.3k
3d
WebView makes website content unaccessible on the top/bottom edges
I'm being faced with an issue when using SwiftUI's WebView on iOS 26. In many websites, the top/bottom content is unaccessible due to being under the app's toolbars. It feels like the WebView doesn't really understand the safe areas where it's being shown, because the content should start right below the navigation bar, and only when the user scrolls down, the content should move under the bar (but it's always reachable if the users scroll back up). Here's a demo of the issue: Here's a 'fix' by ensuring that the content of the WebView never leaves its bounds. But as you can see, it feels out of place on iOS 26 (would be fine on previous OS versions if you had a fully opaque toolbar): Code: struct ContentView: View { var body: some View { NavigationStack { WebView(url: URL(string: "https://apple.com")).toolbar { ToolbarItem(placement: .primaryAction) { Button("Top content covered, unaccessible.") {} } } } } } Does anyone know if there's a way to fix it using some sort of view modifier combination or it's just broken as-is?
14
1
480
3d
listRowBackground vs swipeActions ios26 compatibility
Hi! On iOS 26, Apple’s Mail app shows an effect where a list row gets rounded corners while you’re swiping (so the row visually “matches” the rounded swipe buttons). In my app I’m using SwiftUI List + .swipeActions. I also need a custom row tint (e.g. subtle red/gray highlight based on state). The problem is: If I apply my tint using .background / .clipShape, it moves with the row content during swipe and looks wrong. If I use .listRowBackground(...), I keep the tint, but I don’t get the same rounded-corners “morphing” effect as in Mail (or it looks inconsistent). Question: What’s the correct way in iOS 26 to keep a custom row tint and get the system-style rounded corners / liquid-glass effect while swiping?
Topic: UI Frameworks SubTopic: SwiftUI
0
0
53
3d
Why is ScreenCaptureKit throttled to about 7 fps?
I have an app that records a 32 x 32 rect under the cursor as the user moves it around and it sends it to Flutter. It suffers from major lag. Instead of getting 30 fps, I get about 7 fps. That is, there are significant lags between screen grabs. This on an Intel Mac mini x64 with 15.7.3 and one display. flutter: NATIVE: ExplodedView framesIn=2 timeSinceStart=1115.7ms gapSinceLastFrame=838.8ms flutter: NATIVE: ExplodedView framesIn=4 timeSinceStart=1382.6ms gapSinceLastFrame=149.9ms flutter: NATIVE: ExplodedView framesIn=5 timeSinceStart=1511.0ms gapSinceLastFrame=128.4ms flutter: NATIVE: ExplodedView framesIn=7 timeSinceStart=1698.3ms gapSinceLastFrame=102.9ms flutter: NATIVE: ExplodedView STOP polling totalTime=4482.6ms framesIn=28 framesSent=28 acks=28 Here's a testable excerpt: import ScreenCaptureKit import CoreMedia import CoreVideo import QuartzCore final class Test: NSObject, SCStreamOutput, SCStreamDelegate { private let q = DispatchQueue(label: "cap.q") private var stream: SCStream? private var lastFrameAt: CFTimeInterval = 0 private var frames = 0 func start() { SCShareableContent.getExcludingDesktopWindows(false, onScreenWindowsOnly: true) { content, err in guard err == nil, let display = content?.displays.first else { print("shareableContent error: \(String(describing: err))"); return } let filter = SCContentFilter(display: display, excludingWindows: []) let config = SCStreamConfiguration() config.showsCursor = false config.queueDepth = 1 config.minimumFrameInterval = CMTime(value: 1, timescale: 30) config.pixelFormat = kCVPixelFormatType_32BGRA config.width = 32 config.height = 32 config.sourceRect = CGRect(x: 100, y: 100, width: 32, height: 32) let s = SCStream(filter: filter, configuration: config, delegate: self) try! s.addStreamOutput(self, type: .screen, sampleHandlerQueue: self.q) self.stream = s s.startCapture { startErr in print("startCapture err=\(String(describing: startErr))") } // Optional: move sourceRect at 30Hz (cursor-follow simulation) Timer.scheduledTimer(withTimeInterval: 1.0/30.0, repeats: true) { _ in let c2 = SCStreamConfiguration() c2.showsCursor = false c2.queueDepth = 1 c2.minimumFrameInterval = CMTime(value: 1, timescale: 30) c2.pixelFormat = kCVPixelFormatType_32BGRA c2.width = 32 c2.height = 32 let t = CACurrentMediaTime() c2.sourceRect = CGRect(x: 100 + (sin(t) * 50), y: 100, width: 32, height: 32) s.updateConfiguration(c2) { _ in } } } } func stream(_ stream: SCStream, didOutputSampleBuffer sb: CMSampleBuffer, of type: SCStreamOutputType) { guard type == .screen else { return } let now = CACurrentMediaTime() let gapMs = (lastFrameAt == 0) ? 0 : (now - lastFrameAt) * 1000 lastFrameAt = now frames += 1 if frames <= 10 || frames % 60 == 0 { print("frames=\(frames) gapMs=\(String(format: "%.1f", gapMs))") } } }
0
0
93
3d
Navigation title flickers when tab is changed when used with a List / Form
Problem When a List / Form is added inside a TabView and navigationTitle is set, then switching between tabs causes the navigation title to flicker. Feedback: FB21436493 Environment Xcode: 26.2 (17C52) iOS: 26.2 (23C55) Reproducible on: Both simulator and device Root cause When List / Form is commented out, issue doesn't occur Steps to Reproduce Run app on iOS Switch between tabs Notice that the navigation title flickers Code ContentView import SwiftUI struct ContentView: View { @State private var selectedTab = TabItem.red var body: some View { NavigationStack { TabView(selection: $selectedTab) { ForEach(TabItem.allCases, id: \.self) { tab in Tab(tab.rawValue, systemImage: tab.systemImageName , value: tab) { // Problem occurs with a List / Form // Commenting out list works without flickering title List { Text(tab.rawValue) } } } } .navigationTitle(selectedTab.rawValue) } } } TabItem enum TabItem: String, CaseIterable { case red case green case blue var systemImageName: String { switch self { case .red: "car" case .green: "leaf" case .blue: "bus" } } } Screen recording:
Topic: UI Frameworks SubTopic: SwiftUI
3
0
253
4d
Button Touch Not Canceled in ScrollView on Modal in SwiftUI for iOS 18
When displaying a view with a Button inside a ScrollView using the sheet modifier, if you try to close the sheet by swiping and your finger is touching the Button, the touch is not canceled. This issue occurs when building with Xcode 16 but does not occur when building with Xcode 15. Here is screen cast. https://drive.google.com/file/d/1GaOjggWxvjDY38My4JEl-URyik928iBT/view?usp=sharing Code struct ContentView: View { @State var isModalPresented: Bool = false var body: some View { ScrollView { Button { debugPrint("Hello") isModalPresented.toggle() } label: { Text("Hello") .frame(height: 44) } Button { debugPrint("World") } label: { Text("World") .frame(height: 44) } Text("Hoge") .frame(height: 44) .contentShape(Rectangle()) .onTapGesture { debugPrint("Hoge") } } .sheet(isPresented: $isModalPresented) { ContentView() } } }
15
19
2.7k
5d
Keyboard Toolbar Padding iOS26
When I create a SwiftUI toolbar item with placement of .keyboard on iOS 26, the item appears directly on top of and in contact with the keyboard. This does not look good visually nor does it match the behavior seen in Apple's apps, such as Reminders. Adding padding to the contents of the toolbar item only expands the size of the item but does not separate the capsule background of the item from the keyboard. How can I add vertical padding or spacing to separate the toolbar item capsule from the keyboard?
Topic: UI Frameworks SubTopic: SwiftUI
8
7
611
5d
SwiftUI @State Updates Not Reflecting in UI Until View Reconstruction (Xcode Preview & Device)
Issue Description I'm experiencing a bizarre SwiftUI state update issue that only occurs in Xcode development environment (both Canvas preview and device debugging), but does not occur in production builds downloaded from App Store. Symptom: User taps a button that modifies a @State variable inside a .sheet Console logs confirm the state HAS changed But the UI does not update to reflect the new state Switching to another file in Xcode and back to ContentView instantly fixes the issue The production build (same code) works perfectly fine Environment Xcode: 16F6 (17C52) iOS: 26.2 (testing on iPhone 13) macOS: 25.1.0 (Sequoia) SwiftUI Target: iOS 15.6+ Issue: Present in both Xcode Canvas and on-device debugging Production: Same code works correctly in App Store build (version 1.3.2) Code Structure Parent View (ContentView.swift) struct ContentView: View { @State private var selectedSound: SoundTheme = .none @State private var showSoundSheet = false var body: some View { VStack { // Display button shows current selection SettingButton( title: "Background Sound", value: getLocalizedSoundName(selectedSound) // ← Not updating ) { showSoundSheet = true } } .sheet(isPresented: $showSoundSheet) { soundSelectionView } } private var soundSelectionView: some View { ForEach(SoundTheme.allCases) { sound in Button { selectedSound = sound // ← State DOES change (confirmed in console) // Audio starts playing correctly audioManager.startAmbientSound(sound) } label: { Text(sound.name) } } } private func getLocalizedSoundName(_ sound: SoundTheme) -> String { // Returns localized name return sound.localizedName }} What I've Tried Attempt 1: Adding .id() modifier SettingButton(...) .id(selectedSound) // Force re-render when state changes Result: No effect Attempt 2: Moving state modification outside withAnimation // Before (had animation wrapper):withAnimation { selectedSound = sound}// After (removed animation):selectedSound = sound Result: No effect Attempt 3: Adding debug print() statements selectedSound = soundprint("State changed: (selectedSound)") // ← Adding this line FIXES the issue! Result: Mysteriously fixes the issue! But removing print() breaks it again. This suggests a timing/synchronization issue in Xcode's preview system. Observations What works: ✅ Console logs confirm state changes correctly ✅ Switching files in Xcode triggers view reconstruction → everything works ✅ Production build from App Store works perfectly ✅ Adding print() statements "fixes" it (likely changes execution timing) What doesn't work: ❌ Initial file load in Xcode ❌ Hot reload / incremental updates ❌ Both Canvas preview and on-device debugging Workaround that works: Click another file in Xcode Click back to ContentView.swift Everything works normally Key Question Is this a known issue with Xcode 16's SwiftUI preview/hot reload system? The fact that: Same exact code works in production Adding print() "fixes" it File switching triggers reconstruction that fixes it ...all suggest this is an Xcode tooling issue, not a code bug. However, it makes development extremely difficult as I can't reliably test changes without constantly switching files or killing the app. What I'm Looking For Confirmation: Is this a known Xcode 16 issue? Workaround: Any better solution than constantly switching files? Root cause: What's causing this state update timing issue? Any insights would be greatly appreciated!
Topic: UI Frameworks SubTopic: SwiftUI
6
0
336
6d
In Mac app, when the Settings view that uses `@Environment(\.dismiss)` it causes the subview's models to be created multiple times.
Problem For a mac app, when the Settings view that uses @Environment(\.dismiss) it causes the subview's models to be created multiple times. Environment macOS: 26.2 (25C56) Feedback FB21424864 Code App @main struct DismissBugApp: App { var body: some Scene { WindowGroup { ContentView() } Settings { SettingsView() } } } ContentView struct ContentView: View { var body: some View { Text("Content") } } SettingsView struct SettingsView: View { @Environment(\.dismiss) private var dismiss var body: some View { VStack { Text("Settings") SectionAView() } } } SectionAView struct SectionAView: View { @State private var model = SectionAViewModel() var body: some View { Text("A") .padding(40) } } SectionAViewModel @Observable class SectionAViewModel { init() { print("SectionAViewModel - init") } deinit { print("SectionAViewModel - deinit") } } Steps to reproduce (refer to the attached video) 1 - Run the app on the mac 2 - Open app's Settings 3 - Notice the following logs being printed in the console: SectionAViewModel - init SectionAViewModel - init 4 - Tap on some other app, so that the app loses focus 5 - Notice the following logs being printed in the console: SectionAViewModel - init SectionAViewModel - deinit 6 - Bring the app back to focus 7 - Notice the following logs being printed in the console: SectionAViewModel - init SectionAViewModel - deinit Refer to screen recording
Topic: UI Frameworks SubTopic: SwiftUI
0
0
160
1w
ToolbarItem with .sharedBackgroundVisibility(.hidden) causes rectangular rendering artifact during navigation transitions on iOS 26
Description: When following Apple's WWDC guidance to hide the default Liquid Glass background on a ToolbarItem using .sharedBackgroundVisibility(.hidden) and draw a custom circular progress ring, a rectangular rendering artifact appears during navigation bar transition animations (e.g., when the navigation bar dims/fades during a push/pop transition). Steps to Reproduce: Create a ToolbarItem with a custom circular view (e.g., a progress ring using Circle().trim().stroke()). Apply .sharedBackgroundVisibility(.hidden) to hide the default Liquid Glass background. Navigate to a detail view (triggering a navigation bar transition animation). Observe the ToolbarItem during the transition. Expected Result: The custom circular view should transition smoothly without any visual artifacts. Actual Result: A rectangular bounding box artifact briefly appears around the custom view during the navigation bar's dimming/transition animation. The artifact disappears after the transition completes. Attempts to Resolve (All Failed): Using .frame(width: 44, height: 44) with .aspectRatio(1, contentMode: .fit) Using .fixedSize() instead of explicit frame Using Circle().fill() as a base view with .overlay for content Using Button with .buttonStyle(.plain) and Color.clear placeholder Various combinations of .clipShape(Circle()), .contentShape(Circle()), .mask(Circle()) Workaround Found (Trade-off): Removing .sharedBackgroundVisibility(.hidden) eliminates the rectangular artifact, but this prevents customizing the Liquid Glass appearance as intended by the API. Code Sample: swift if #available(iOS 26.0, *) { ToolbarItem { Button { // action } label: { Color.clear .frame(width: 32, height: 32) .overlay { ZStack { // Background arc (3/4 circle) Circle() .trim(from: 0, to: 0.75) .stroke(Color.blue.opacity(0.3), style: StrokeStyle(lineWidth: 4, lineCap: .round)) .rotationEffect(.degrees(135)) .frame(width: 28, height: 28) // Progress arc Circle() .trim(from: 0, to: 0.5) // Example: 50% progress .stroke(Color.blue, style: StrokeStyle(lineWidth: 4, lineCap: .round)) .rotationEffect(.degrees(135)) .frame(width: 28, height: 28) Text("50") .font(.system(size: 12, weight: .bold)) .foregroundStyle(Color.blue) Text("100") .font(.system(size: 8, weight: .bold)) .foregroundStyle(.primary) .offset(y: 12) } .background { Circle() .fill(.clear) .glassEffect(.clear.interactive(), in: Circle()) } } } .buttonStyle(.plain) } .sharedBackgroundVisibility(.hidden) // ⚠️ This modifier causes the rectangular artifact during transitions } Environment: iOS 26 Beta
Topic: UI Frameworks SubTopic: SwiftUI
1
1
102
1w
What is the best way to push iOS26 List content up on TextField keyboard focused?
Code example: // // ListSafeAreaBarKeyboardTextField.swift // Exploration import SwiftUI import Foundation struct ListSafeAreaBarKeyboardTextField: View { @State private var typedText: String = "" @FocusState private var focusingTextField: Bool private let items = Array(1...16) var body: some View { ScrollViewReader { proxy in List(items, id: \.self) { number in Text("Item \(number)") .id(number) } .onAppear { if let lastItem = items.last { proxy.scrollTo(lastItem, anchor: .bottom) } } .onChange(of: focusingTextField) { oldValue, newValue in // This simply won't work // ~ 12th - 16th item will still get covered by keyboard if newValue == true { // Delay to allow keyboard animation to complete DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { if let lastItem = items.last { withAnimation { proxy.scrollTo(lastItem, anchor: .top) } } } } } } .scrollDismissesKeyboard(.interactively) .safeAreaBar(edge: .bottom) { TextField("Type here", text: $typedText, axis: .vertical) .focused($focusingTextField) // Design .padding(.horizontal, 16) .padding(.vertical, 10) .glassEffect() // Paddings .padding(.horizontal, 24) .padding(.vertical, 12) } } }
1
0
110
1w
SwiftUI's colorScheme vs preferredColorScheme
SwiftUI's colorScheme modifier is said to be deprecated in favour of preferredColorScheme but the two work differently. See the below sample app, colorScheme changes the underlying view colour while preferredColorScheme doesn't. Is that a bug of preferredColorScheme? import SwiftUI struct ContentView: View { let color = Color(light: .red, dark: .green) var body: some View { VStack { HStack { color.colorScheme(.light) color.colorScheme(.dark) } HStack { color.preferredColorScheme(.light) color.preferredColorScheme(.dark) } } } } #Preview { ContentView() } @main struct TheApp: App { var body: some Scene { WindowGroup { ContentView() } } } extension UIColor { convenience init(light: UIColor, dark: UIColor) { self.init { v in switch v.userInterfaceStyle { case .light: light case .dark: dark case .unspecified: fatalError() @unknown default: fatalError() } } } } extension Color { init(light: Color, dark: Color) { self.init(UIColor(light: UIColor(light), dark: UIColor(dark))) } }
1
0
232
1w