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

How to achieve this vibrant background effect on iOS?
Hi everyone, I'm trying to reproduce an effect that Apple has created for the Contacts app on iOS, iPadOS and MacOS v26.4 where the contact card is displayed with a nice material frosted background that blends well with the underlying background. I love this effect and I want to use it in my app to display different information. As you can see in the screenshot, the list rows have a frosted background (probably thinMaterial) combined with a vibrant effect that adapts to the underlying view background. Additionally, the fields labels and icons also have a nice effect. I've tried everything but I'm unable to accurately recreate this effect. I tried applying a Rectangle with a material background listRowBackground but this resulted in something different than what Apple is using (either too light, too dark, or simply not vibrant). I've even tried SwiftUIVisualEffects swift package which can apply a vibrancy effect. However the result is still not the same as the one you see in the screenshot, with the correct contrast between background and labels. Any guidance would be appreciated. Thank you 🙏🏻
4
0
475
May ’26
apply .activityBackgroundTint modifier in smartstack
On iOS 26, when using .activityBackgroundTint modifiers to change the background color in the Activity Kit, the changes do not appear to apply correctly in Smart Stack. While the color changes as expected, the background is rendered as simply transparent without a glass effect which reduces readability. The glass effect is applied only when activityBackgroundTint is not used.
0
0
348
May ’26
tabViewBottomAccessory does not inherit tab bar vibrancy / foregroundStyle behavior
Hi, I’m experimenting with the new tabViewBottomAccessory API and I’m running into an inconsistency with how colors are handled compared to the native tab bar items. Context When using a TabView, the system tab bar automatically adapts its foreground color (icons and labels) based on the background content (light/dark, images, etc.). This is the expected “vibrancy” behavior. However, when adding content via .tabViewBottomAccessory, the foreground color does not seem to follow the same logic. Minimal example : import SwiftUI struct ContentView: View { var body: some View { TabView { Tab("Home", systemImage: "house") { Text("Home") .frame(maxWidth: .infinity, maxHeight: .infinity) .ignoresSafeArea() } Tab("New", systemImage: "squareshape.split.2x2") { Text("New") .frame(maxWidth: .infinity, maxHeight: .infinity) .foregroundStyle(.white) .background(Color.black) .ignoresSafeArea() } } .tabViewBottomAccessory { HStack { Image(systemName: "command.square") Text("Message test") Spacer() Image(systemName: "play.fill") } .padding(.horizontal, 20) .foregroundStyle(.primary) } } } Observed behavior Tab bar icons and labels correctly switch between dark and light depending on the background. Content inside .tabViewBottomAccessory remains black, even when .foregroundStyle(.primary) is used. Expected behavior I would expect .tabViewBottomAccessory content to: Either inherit the same vibrancy/foreground adaptation as the tab bar items Or have a documented way to match that behavior I want to reuse the Apple Music Navigation
Topic: UI Frameworks SubTopic: SwiftUI
0
0
110
May ’26
SwiftUI TabView(.sidebarAdaptable) does not reliably animate content resize when switching between sidebar and top tab bar on iPad
Hi everyone, I’m building an iPad app in SwiftUI using the adaptive tab navigation pattern: Tab(value: .overview) { OverviewView() } label: { Label("Overview", systemImage: "archivebox") } Tab(value: .gallery) { GalleryView() } label: { Label("Gallery", systemImage: "shippingbox") } Tab(value: .canvas) { CanvasView() } label: { Label("Canvas", systemImage: "rectangle") } Tab(value: .record) { recordView } label: { Label("Record", systemImage: "plus") } } .tabViewStyle(.sidebarAdaptable) .tabViewCustomization($tabCustomization) The issue is that when the adaptive tab bar switches between the sidebar placement and the top bar placement on iPad, the content area resize animation is unreliable. The system navigation chrome changes correctly, but some tab contents jump directly to their final width instead of smoothly animating with the sidebar/top bar transition. Interestingly, one of my record views appears to animate consistently, so it seems the system transition itself is possible, but some view hierarchy or navigation structure may be preventing the animation in other tabs. Each major tab currently owns its own NavigationStack. For example, OverviewView, GalleryView, and CanvasView each have a NavigationStack as their root view. The Record tab conditionally shows different recording views, and one of those views also contains its own NavigationStack. I have already tried several approaches, but none solved the issue reliably: Observing @Environment(.tabBarPlacement) and adding .animation(..., value:) Reporting tabBarPlacement upward using a PreferenceKey and wrapping the update in withAnimation Wrapping tab contents in GeometryReader or other outer layout containers Temporarily removing .tabViewCustomization($tabCustomization) and .customizationID(...) Reducing the implementation to the simplest documented TabView(selection:) + Tab(...) + .tabViewStyle(.sidebarAdaptable) structure Some of these attempts actually made the animation behavior worse, so I reverted them. My questions are: 1.Is the content area expected to animate automatically when TabView(.sidebarAdaptable) changes between sidebar and top bar placement on iPad? 2.Is it recommended for each tab to own its own NavigationStack in this setup? 3.Could tabViewCustomization(:) or customizationID(:) affect the sidebar/top bar transition animation? 4.Is there an official SwiftUI pattern for preserving the system animation transaction during this adaptive tab bar placement change? 5.If this is expected behavior or a current limitation, what structure would Apple recommend for this kind of iPad navigation? Thanks in advance!
Topic: UI Frameworks SubTopic: SwiftUI
0
0
125
May ’26
Styling LabeledContent inside a Form on macOS?
On macOS 26, the Label part of a LabeledContent control and the Section.header part of a Section do not seem to honour view modifiers like .controlSize(.small) when used inside a Form with .formStyle(.grouped). Is there a way to make them respect the control size? Example: Form { Section("Details") { LabeledContent("Company", value: "Apple") } } .formStyle(.grouped) .controlSize(.small) // This only effects 'Apple' This produces a view where the value "Apple" is using a smaller font size but the label and the section header are not. I've tried (I think) almost every variation I can think of in terms of creating a LabeledContent and applying .controlSize but all of them come up short. The Form appears to always override my view modifiers for the section heading and label. Example 2: Form { Section { LabeledContent { Text("Company") .controlSize(.small) // Has no effect. } label: { Text("Apple") // Correctly resized to .small. } } header: { Text("Details") .controlSize(.small) // Has no effect. } } .formStyle(.grouped) .controlSize(.small) The best I've been able to come up with is a custom LabeledContentStyle that manually applies the layout and the styling, but that requires I explicitly "recreate" the macOS look-and-feel of left aligned labels and right aligned values by way of an HStack and Spacer. Have I overlooked a way to style a Form or LabeledContent that would provide the results I'm looking for?
0
0
79
Apr ’26
SwiftUI TextField.accessibilityIdentifier is not propagated to the underlying UITextField instance.
When applying the .accessibilityIdentifier(_:) modifier to a SwiftUI TextField, the identifier is correctly added to the SwiftUI Accessibility Tree (visible in Accessibility Inspector), but it is not assigned to the accessibilityIdentifier property of the underlying UITextField instance. This causes issues for developers who monitor global notifications, such as UITextField.textDidChangeNotification. When a notification is received, the object (the UITextField) has a nil identifier, making it impossible to programmatically determine which specific text field triggered the event. Steps to Reproduce: Create a SwiftUI view containing a TextField. Apply .accessibilityIdentifier("TargetTextField") to that TextField. Set up an observer (via NotificationCenter or onReceive) for UITextField.textDidChangeNotification. Run the app and type into the text field. Inspect the accessibilityIdentifier property of the UITextField object provided by the notification. Expected Result: The UITextField.accessibilityIdentifier should be "TargetTextField". Actual Result: The UITextField.accessibilityIdentifier is nil.
1
0
270
Apr ’26
Timing issue with updating two state variables
I have a SwiftUI view with: @State var url: URL? @State var isShowingBrowser: Bool func displayURL(url: URL) { self.url = url self.isShowingBrowser = true } var body: some View { Group { // ...... } .sheet(isPresented: $isShowingBrowser) { // browser view } } The first time I call displayBrowser, an empty browser sheet appears, with no URL. The second time, it works. It doesn't matter if I reorder the assignments in displayURL. It's like the view refreshes once with a nil URL and isShowingBrowser true, then refreshes again with the URL value. If I move both variable to an @Observable view model class then it works fine - that update seems to happen atomically. For my own project, the view model is the right way to do this, but I was confused by this behavior. What am I missing about SwiftUI?
Topic: UI Frameworks SubTopic: SwiftUI
0
0
236
Apr ’26
Having trouble with RawRespresentable "Expected to decode String but found a dictionary instead."
I want to use AppStorage for a custom struct I am using struct Activities { var name: String var age: Int } struct ContentView: View { @AppStorage("key") private var activities: Activities = .init(name: "Albert", age: 42) var body: some View { VStack { TextField("Activity Name", text: $activities.name) } } } The above code generates a compiler warning, recommending I add RawRepresentable conformance. So I've added it like this: extension Activities: RawRepresentable { public init?(rawValue: String) { guard let data = rawValue.data(using: .utf8) else { return nil } do { let result = try JSONDecoder().decode(Activities.self, from: data) self = result } catch { print(error) return nil } } var rawValue: String { guard let data = try? JSONEncoder().encode(self), let result = String(data: data, encoding: .utf8) else { return "{}" } return result } } This leads to a stack overflow because calling encode from rawValue calls rawValue. :-( I overcame this by declaring Codable conformance and overriding the default Encodable implementation: extension Activities: Codable { enum CodingKeys: String, CodingKey { case name case age } func encode(to encoder: any Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(name, forKey: .name) try container.encode(age, forKey: .age) } } This solves the stack overflow, but now init?(rawValue: String) is failing and I'm not sure why. When I set a breakpoint in my catch block I see the following: (lldb) po error ▿ DecodingError ▿ typeMismatch : 2 elements - .0 : Swift.String ▿ .1 : Context - codingPath : 0 elements - debugDescription : "Expected to decode String but found a dictionary instead." - underlyingError : nil (lldb) po rawValue {"name":"Albert2","age":42} (lldb) po data ▿ 27 bytes - count : 27 ▿ bytes : 27 elements - 0 : 123 - 1 : 34 - 2 : 110 - 3 : 97 - 4 : 109 - 5 : 101 - 6 : 34 - 7 : 58 - 8 : 34 (truncated to save space for posting :-)
2
0
573
May ’26
Tapping a .searchSuggestions item inside a NavigationStack dismisses the search controller
Since iOS26, I've been running into an issue with using a NavigationStack with .searchSuggestions, and using searchable with placement: .navigationBarDrawer(displayMode: .always) With this, the search is activated and search suggestions list is displayed, but tapping on the search suggestions dismisses the whole search control without doing selecting the search suggestion item. This doesn't happen on iPhone, and doesn't happen on iPadOS 18.5 or below. And removing the 'placement' argument also fixes the issue. NavigationStack { List { /// ... } .searchable( text: $searchText, tokens: $searchTokens, isPresented: $isSearchPresented, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search timestamps" ) { token in Label(token.title, systemImage: token.systemImage) } .searchSuggestions { ForEach(suggestedTokens) { token in Label(token.title, systemImage: token.systemImage) .searchCompletion(token) } } .toolbar { ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } I have a test sample app with this, and created FB22639453 The same problem happens in UIKit as well, when using UISearchController with UINavigationItems' searchController.
1
0
137
Apr ’26
SF Symbols .replace animation is partially missing
In SF Symbols 7, I'm observing a discrepancy between the .replace animation previewed in the SF Symbols app and the result when using the code template the app provides. Expected behavior: When previewing the .replace animation in the SF Symbols app (with Magic Replace preferred), the transition looks like: Actual behavior: When I implement the animation using the exact code template generated by the SF Symbols app, the result looks like: My code: struct PlaygroundSwiftUIView: View { @State var name = "folder.circle" var body: some View { Image(systemName: name) .font(.system(size: 60)) .contentTransition(.symbolEffect(.replace)) .onTapGesture { name = "tree" } } } #Preview { PlaygroundSwiftUIView() } The animation rendered in my app does not match the preview shown in the SF Symbols app. The drawOff animation is partially missing. Is there something missing from the code template, or is there an additional configuration step required to achieve the correct Replace effect? or is this a bug?
2
0
274
3w
SF Symbols .replace animation is weird
In SF Symbols 7, I'm observing a discrepancy between the .replace animation previewed in the SF Symbols app and the result when using the code template the app provides. Expected behavior: When previewing the .replace animation in the SF Symbols app (with Magic Replace preferred), the transition looks like: Actual behavior: When I implement the animation using the exact code template generated by the SF Symbols app, the result looks like: My code: struct PlaygroundSwiftUIView: View { @State var name = "folder.circle" var body: some View { Image(systemName: name) .font(.system(size: 60)) .contentTransition(.symbolEffect(.replace)) .onTapGesture { name = "tree" } } } #Preview { PlaygroundSwiftUIView() } The animation rendered in my app does not match the preview shown in the SF Symbols app. The drawOff animation is partly missing. Is there something missing from the code template, or is there an additional configuration step required to achieve the correct Replace effect?
0
0
138
Apr ’26
Can contextMenu respect onLongPressGesture of a child element?
Hi, I have a list cell with a play button and a text label. When tapping the play button, it plays an audio, and when long-pressed, it plays the audio slowly. The long press works as per the example code below, but once a contextMenu is added, the long-press gesture of the play button is ignored (even though it's a small element in the cell), and the context menu is presented instead. Is there a way to allow for the context menu long-press to respect the long-press gesture of a child element in the cell on which it's defined? I also tried with highPriorityGesture but to no effect. Example code: HStack { Button { print("Play") } label: { Image(systemName: "play.circle") .onLongPressGesture(minimumDuration: 0.5) { print("Play slowly") } } Text("Audio cell") .frame(maxWidth: .infinity, alignment: .leading) } .contextMenu { Button("Hello") { print("hello") } Button("Goodbye") { print("goodbye") } }
0
0
117
Apr ’26
.buttonStyle(.glass) background changes abruptly between 50pt and 51pt in dark mode
[Submitted as FB22612121] A SwiftUI Button using .buttonStyle(.glass) with .buttonBorderShape(.capsule) changes its background abruptly when its size goes from 50×50 to 51×51 points in dark mode. This appears to be a threshold in opacity/material rather than a smooth size-based change. The sample shows identical buttons at 40, 50, 51, and 60 points, with a clear jump between 50 and 51. Measured RGB values shift from 19,19,19 to 30,30,30. The effect also varies with the background, which points to a material/opacity change rather than a fixed fill. ENVIRONMENT iOS 26.4.1 (23E254a) iOS 26.5 (23F5059e) REPRO STEPS Create a new iOS SwiftUI project. Replace ContentView with the sample code below. Run the app or open ContentView in SwiftUI Preview (dark mode). Observe the buttons at 40×40, 50×50, 51×51, and 60×60. Compare the 50pt and 51pt buttons. ACTUAL The background changes abruptly between 50pt and 51pt. The 51pt button uses a noticeably different opacity/material, producing a visible jump in dark mode. EXPECTED The glass background should remain visually consistent or change smoothly as size changes by 1 point. 50pt and 51pt buttons should not have a discontinuous difference. SCREENSHOT SAMPLE CODE struct ContentView: View { private let sizes: [CGFloat] = [40, 50, 51, 60] var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { Text("Glass button dark-mode size jump") .font(.headline) Text("All buttons use .buttonStyle(.glass). Only the label frame changes.") .font(.footnote) .foregroundStyle(.secondary) ForEach(Array(sizes.enumerated()), id: \.offset) { index, size in HStack(spacing: 14) { Button { } label: { Text("\(index + 1)") .font(.system(size: size * 0.42, weight: .medium)) .frame(width: size, height: size) } .buttonStyle(.glass) .buttonBorderShape(.capsule) Text("label frame: \(Int(size)) x \(Int(size))") .font(.callout.monospacedDigit()) .foregroundStyle(.secondary) } } } .padding(24) } .preferredColorScheme(.dark) } }
Topic: UI Frameworks SubTopic: SwiftUI
1
0
232
May ’26
How to Indicate Selected State for a Menu Toolbar Item (Filter) in SwiftUI?
hi, On my page’s toolbar, I have a toolbar item that is implemented as a menu. Its purpose is to filter the content displayed on the page, similar to the filtering feature in the Photos app. When a user selects a filter option, I want the toolbar item to appear highlighted to indicate the active state. I came across the following guidance in the Human Interface Guidelines: Provide a selected-state version of an interface icon only if necessary. You don’t need to provide selected and unselected appearances for an icon that’s used in standard system components such as toolbars, tab bars, and buttons. The system updates the visual appearance of the selected state automatically. An image of two toolbar buttons that share a background. The left button shows the Filter icon in a selected state, using a blue tint color for its background. The right button shows the More icon in an unselected state, using the default appearance for toolbar buttons. In a toolbar, a selected icon receives the app’s accent color. However, I’m not sure how to actually implement or control the selected state for my toolbar item. Here is a snippet of my code: ToolbarItem(placement: .topBarTrailing) { Menu { Section { LayoutPickerView(layoutOption: $layoutOption) } Section { SortPickerView(sortOption: $viewModel.sortOption) } Section { Menu { Toggle( isOn: Binding( get: { viewModel.filterPlatforms.isEmpty }, set: { if $0 { viewModel.filterPlatforms.removeAll() } } ) ) { HStack { Image(systemName: "square.grid.3x3") .resizable() .scaledToFit() .frame(width: 30, height: 30) Text(Localized.Content.filterAllPlatforms) } } .menuActionDismissBehavior(.disabled) Divider() ForEach(viewModel.availablePlatforms(from: contents)) { platform in Toggle(isOn: viewModel.platformBinding(for: platform)) { HStack { CachedPlatformIconView(urlString: platform.iconUrl, size: 30) Text(platform.name) } } .menuActionDismissBehavior(.disabled) } } label: { Text(Localized.Content.filterMenu) Text(viewModel.filterPlatforms.map(\.name).joined(separator: String(localized: Localized.Content.separator))) } if !viewModel.filterPlatforms.isEmpty { Button { viewModel.filterPlatforms.removeAll() } label: { Text(Localized.Content.filterClear) } } } } label: { Image(systemName: "line.3.horizontal.decrease") } }
Topic: UI Frameworks SubTopic: SwiftUI
0
0
139
Apr ’26
How to detect if a binding is from a state or a constant?
Hi, I'm trying to create a custom TextField component where we can have our own custom FormatStyle as a param and then it will change the value binding according to the FormatStyle. It worked with State<Any?> like for example $textValue. But when I use .constant(2000) for instance, the Formatting doesn't work. So is there any way to detect whether the value param is constant or not? Thank you.
0
0
241
Apr ’26
SwiftUI Text rendering with too small height / one line missing causing unexpected text truncation on iPhone devices
FB: FB22577211 The following trivial SwiftUI Text rendering causes wrong text layout and truncated text. The text should take the required height to render the text without truncation. Adding fixedSize does also not solve this. This bug only happens on devices and not on the simulator. Confirmed with iPhone 15 and iOS 26.4.1 but my colleague used another iPhone so it’s multiple iPhone devices. import SwiftUI let txt = """ Es sollte die erste Japan-Tournee von vielen werden, kein anderes Land – abgesehen von Österreich und der Schweiz – bereisten die Berliner Philharmoniker häufiger. Wie kam es zu dem überschäumend herzlichen Empfang, der dem Orchester bei seinem ersten Gastspiel in Tokio bereitet wurde und wie wurde das Land zu einer »zweiten Heimat« für die Berliner? Ein konkreter historischer Grundstein für das hohe Ansehen klassischer Musik »made in Germany« in Japan wurde bereits im 19. Jahrhunderts gelegt: Als Teil von umfassenden gesellschaftlichen Modernisierungsmaßnahmen vergab die Regierung ab 1868 Stipendien an junge japanische Intellektuelle, damit diese an den besten internationalen Instituten studieren konnten. Berlin wurde – neben Wien – als globales Zentrum der Musik betrachtet, und so erhielten viele japanische Studierende um die Jahrhundertwende die Gelegenheit, von Komponisten wie etwa Max Bruch zu lernen. Zurück in der Heimat, teilten sie ihre Begeisterung für die europäische Kunstmusik sowie das Wissen um die instrumentale und kompositorische Praxis der klassisch-romantischen Tradition. """ struct ContentView: View { var body: some View { VStack { Text(txt) } .padding(.leading, 20) .padding(.trailing, 20) .frame(maxWidth: .infinity) } } This is also enough: Text(txt) .padding(.horizontal, 20) .fixedSize(horizontal: false, vertical: true) Expected: Text is rendered without truncation / ellipsis. Actual: Text is rendered with too small height / missing one line so it’s truncated / with ellipsis.
10
0
660
May ’26
segmented picker style causes runtime warning
On OSX, using a segmented picker style causes the following warning to be emitted (when a different selection is made) : "Publishing changes from within view updates is not allowed, this will cause undefined behavior." The warning is not emitted using the 'Preview Canvas' only when running the app. Changing the picker style to automatic also fixes it, but the segmented style is used extensively. Tested using XCode 26.4.1 on MacOS 26.3.1 --- view --- import SwiftUI internal import Combine enum Mode : String { case one, two, three } class MyObject : ObservableObject { @Published var mode : Mode = .one } struct ContentView: View { @StateObject var obj = MyObject() var body: some View { VStack { Picker("Mode",selection: $obj.mode) { Text("One").tag(Mode.one) Text("Two").tag(Mode.two) Text("Three").tag(Mode.three) } .pickerStyle(.segmented) } .padding() } } #Preview { ContentView() } --- app --- import SwiftUI @main struct SwiftUIBugApp: App { var body: some Scene { WindowGroup { ContentView() } } }
6
0
117
Apr ’26
Apple Watch Complication with SF Symbols slightly off-center
I have some simple circular complications, that use a ZStack with SFSymbols. On high contrast Watch Faces, I noted that the circle is slightly off to the top leading side. I tried to set the ZStack alignment to center, fiddled around with Spacers, but I could not get it centered. Is that a bug or am I missing something? struct CircularWidgetDashed: View { var entry: Provider.Entry var body: some View { ZStack { Image(systemName: "circle.dashed") .resizable() .scaledToFit() .foregroundColor(.green) Text("\(entry.online)/\(entry.total)") .foregroundStyle(.primary) .font(.caption) .fontWeight(.semibold) } .widgetAccentable() } }
4
0
259
Apr ’26
SearchFieldPlacement.navigationBarDrawer in NavigationSplitView detail ignores sidebar width on first rendering.
When a NavigationSplitView detail column shows a View that uses .searchable(text: $searchText, placement: .navigationBarDrawer), the search bar extends under the sidebar region, on the first View render only. After any event that triggers a View refresh (such as switching away and back to the View, editing the search text, or resizing the window) the search field is positioned correctly in the detail column’s navigation area. var body: some View { NavigationSplitView { List { Text("Sidebar") } .navigationTitle("Sidebar") } detail: { Text("Detail") .navigationTitle("List") .searchable( text: $searchText, placement: .navigationBarDrawer ) } } FB22559713 has been opened.
0
0
118
Apr ’26
How to achieve this vibrant background effect on iOS?
Hi everyone, I'm trying to reproduce an effect that Apple has created for the Contacts app on iOS, iPadOS and MacOS v26.4 where the contact card is displayed with a nice material frosted background that blends well with the underlying background. I love this effect and I want to use it in my app to display different information. As you can see in the screenshot, the list rows have a frosted background (probably thinMaterial) combined with a vibrant effect that adapts to the underlying view background. Additionally, the fields labels and icons also have a nice effect. I've tried everything but I'm unable to accurately recreate this effect. I tried applying a Rectangle with a material background listRowBackground but this resulted in something different than what Apple is using (either too light, too dark, or simply not vibrant). I've even tried SwiftUIVisualEffects swift package which can apply a vibrancy effect. However the result is still not the same as the one you see in the screenshot, with the correct contrast between background and labels. Any guidance would be appreciated. Thank you 🙏🏻
Replies
4
Boosts
0
Views
475
Activity
May ’26
apply .activityBackgroundTint modifier in smartstack
On iOS 26, when using .activityBackgroundTint modifiers to change the background color in the Activity Kit, the changes do not appear to apply correctly in Smart Stack. While the color changes as expected, the background is rendered as simply transparent without a glass effect which reduces readability. The glass effect is applied only when activityBackgroundTint is not used.
Replies
0
Boosts
0
Views
348
Activity
May ’26
tabViewBottomAccessory does not inherit tab bar vibrancy / foregroundStyle behavior
Hi, I’m experimenting with the new tabViewBottomAccessory API and I’m running into an inconsistency with how colors are handled compared to the native tab bar items. Context When using a TabView, the system tab bar automatically adapts its foreground color (icons and labels) based on the background content (light/dark, images, etc.). This is the expected “vibrancy” behavior. However, when adding content via .tabViewBottomAccessory, the foreground color does not seem to follow the same logic. Minimal example : import SwiftUI struct ContentView: View { var body: some View { TabView { Tab("Home", systemImage: "house") { Text("Home") .frame(maxWidth: .infinity, maxHeight: .infinity) .ignoresSafeArea() } Tab("New", systemImage: "squareshape.split.2x2") { Text("New") .frame(maxWidth: .infinity, maxHeight: .infinity) .foregroundStyle(.white) .background(Color.black) .ignoresSafeArea() } } .tabViewBottomAccessory { HStack { Image(systemName: "command.square") Text("Message test") Spacer() Image(systemName: "play.fill") } .padding(.horizontal, 20) .foregroundStyle(.primary) } } } Observed behavior Tab bar icons and labels correctly switch between dark and light depending on the background. Content inside .tabViewBottomAccessory remains black, even when .foregroundStyle(.primary) is used. Expected behavior I would expect .tabViewBottomAccessory content to: Either inherit the same vibrancy/foreground adaptation as the tab bar items Or have a documented way to match that behavior I want to reuse the Apple Music Navigation
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
110
Activity
May ’26
SwiftUI TabView(.sidebarAdaptable) does not reliably animate content resize when switching between sidebar and top tab bar on iPad
Hi everyone, I’m building an iPad app in SwiftUI using the adaptive tab navigation pattern: Tab(value: .overview) { OverviewView() } label: { Label("Overview", systemImage: "archivebox") } Tab(value: .gallery) { GalleryView() } label: { Label("Gallery", systemImage: "shippingbox") } Tab(value: .canvas) { CanvasView() } label: { Label("Canvas", systemImage: "rectangle") } Tab(value: .record) { recordView } label: { Label("Record", systemImage: "plus") } } .tabViewStyle(.sidebarAdaptable) .tabViewCustomization($tabCustomization) The issue is that when the adaptive tab bar switches between the sidebar placement and the top bar placement on iPad, the content area resize animation is unreliable. The system navigation chrome changes correctly, but some tab contents jump directly to their final width instead of smoothly animating with the sidebar/top bar transition. Interestingly, one of my record views appears to animate consistently, so it seems the system transition itself is possible, but some view hierarchy or navigation structure may be preventing the animation in other tabs. Each major tab currently owns its own NavigationStack. For example, OverviewView, GalleryView, and CanvasView each have a NavigationStack as their root view. The Record tab conditionally shows different recording views, and one of those views also contains its own NavigationStack. I have already tried several approaches, but none solved the issue reliably: Observing @Environment(.tabBarPlacement) and adding .animation(..., value:) Reporting tabBarPlacement upward using a PreferenceKey and wrapping the update in withAnimation Wrapping tab contents in GeometryReader or other outer layout containers Temporarily removing .tabViewCustomization($tabCustomization) and .customizationID(...) Reducing the implementation to the simplest documented TabView(selection:) + Tab(...) + .tabViewStyle(.sidebarAdaptable) structure Some of these attempts actually made the animation behavior worse, so I reverted them. My questions are: 1.Is the content area expected to animate automatically when TabView(.sidebarAdaptable) changes between sidebar and top bar placement on iPad? 2.Is it recommended for each tab to own its own NavigationStack in this setup? 3.Could tabViewCustomization(:) or customizationID(:) affect the sidebar/top bar transition animation? 4.Is there an official SwiftUI pattern for preserving the system animation transaction during this adaptive tab bar placement change? 5.If this is expected behavior or a current limitation, what structure would Apple recommend for this kind of iPad navigation? Thanks in advance!
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
125
Activity
May ’26
Styling LabeledContent inside a Form on macOS?
On macOS 26, the Label part of a LabeledContent control and the Section.header part of a Section do not seem to honour view modifiers like .controlSize(.small) when used inside a Form with .formStyle(.grouped). Is there a way to make them respect the control size? Example: Form { Section("Details") { LabeledContent("Company", value: "Apple") } } .formStyle(.grouped) .controlSize(.small) // This only effects 'Apple' This produces a view where the value "Apple" is using a smaller font size but the label and the section header are not. I've tried (I think) almost every variation I can think of in terms of creating a LabeledContent and applying .controlSize but all of them come up short. The Form appears to always override my view modifiers for the section heading and label. Example 2: Form { Section { LabeledContent { Text("Company") .controlSize(.small) // Has no effect. } label: { Text("Apple") // Correctly resized to .small. } } header: { Text("Details") .controlSize(.small) // Has no effect. } } .formStyle(.grouped) .controlSize(.small) The best I've been able to come up with is a custom LabeledContentStyle that manually applies the layout and the styling, but that requires I explicitly "recreate" the macOS look-and-feel of left aligned labels and right aligned values by way of an HStack and Spacer. Have I overlooked a way to style a Form or LabeledContent that would provide the results I'm looking for?
Replies
0
Boosts
0
Views
79
Activity
Apr ’26
SwiftUI TextField.accessibilityIdentifier is not propagated to the underlying UITextField instance.
When applying the .accessibilityIdentifier(_:) modifier to a SwiftUI TextField, the identifier is correctly added to the SwiftUI Accessibility Tree (visible in Accessibility Inspector), but it is not assigned to the accessibilityIdentifier property of the underlying UITextField instance. This causes issues for developers who monitor global notifications, such as UITextField.textDidChangeNotification. When a notification is received, the object (the UITextField) has a nil identifier, making it impossible to programmatically determine which specific text field triggered the event. Steps to Reproduce: Create a SwiftUI view containing a TextField. Apply .accessibilityIdentifier("TargetTextField") to that TextField. Set up an observer (via NotificationCenter or onReceive) for UITextField.textDidChangeNotification. Run the app and type into the text field. Inspect the accessibilityIdentifier property of the UITextField object provided by the notification. Expected Result: The UITextField.accessibilityIdentifier should be "TargetTextField". Actual Result: The UITextField.accessibilityIdentifier is nil.
Replies
1
Boosts
0
Views
270
Activity
Apr ’26
Timing issue with updating two state variables
I have a SwiftUI view with: @State var url: URL? @State var isShowingBrowser: Bool func displayURL(url: URL) { self.url = url self.isShowingBrowser = true } var body: some View { Group { // ...... } .sheet(isPresented: $isShowingBrowser) { // browser view } } The first time I call displayBrowser, an empty browser sheet appears, with no URL. The second time, it works. It doesn't matter if I reorder the assignments in displayURL. It's like the view refreshes once with a nil URL and isShowingBrowser true, then refreshes again with the URL value. If I move both variable to an @Observable view model class then it works fine - that update seems to happen atomically. For my own project, the view model is the right way to do this, but I was confused by this behavior. What am I missing about SwiftUI?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
236
Activity
Apr ’26
Having trouble with RawRespresentable "Expected to decode String but found a dictionary instead."
I want to use AppStorage for a custom struct I am using struct Activities { var name: String var age: Int } struct ContentView: View { @AppStorage("key") private var activities: Activities = .init(name: "Albert", age: 42) var body: some View { VStack { TextField("Activity Name", text: $activities.name) } } } The above code generates a compiler warning, recommending I add RawRepresentable conformance. So I've added it like this: extension Activities: RawRepresentable { public init?(rawValue: String) { guard let data = rawValue.data(using: .utf8) else { return nil } do { let result = try JSONDecoder().decode(Activities.self, from: data) self = result } catch { print(error) return nil } } var rawValue: String { guard let data = try? JSONEncoder().encode(self), let result = String(data: data, encoding: .utf8) else { return "{}" } return result } } This leads to a stack overflow because calling encode from rawValue calls rawValue. :-( I overcame this by declaring Codable conformance and overriding the default Encodable implementation: extension Activities: Codable { enum CodingKeys: String, CodingKey { case name case age } func encode(to encoder: any Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(name, forKey: .name) try container.encode(age, forKey: .age) } } This solves the stack overflow, but now init?(rawValue: String) is failing and I'm not sure why. When I set a breakpoint in my catch block I see the following: (lldb) po error ▿ DecodingError ▿ typeMismatch : 2 elements - .0 : Swift.String ▿ .1 : Context - codingPath : 0 elements - debugDescription : "Expected to decode String but found a dictionary instead." - underlyingError : nil (lldb) po rawValue {"name":"Albert2","age":42} (lldb) po data ▿ 27 bytes - count : 27 ▿ bytes : 27 elements - 0 : 123 - 1 : 34 - 2 : 110 - 3 : 97 - 4 : 109 - 5 : 101 - 6 : 34 - 7 : 58 - 8 : 34 (truncated to save space for posting :-)
Replies
2
Boosts
0
Views
573
Activity
May ’26
Tapping a .searchSuggestions item inside a NavigationStack dismisses the search controller
Since iOS26, I've been running into an issue with using a NavigationStack with .searchSuggestions, and using searchable with placement: .navigationBarDrawer(displayMode: .always) With this, the search is activated and search suggestions list is displayed, but tapping on the search suggestions dismisses the whole search control without doing selecting the search suggestion item. This doesn't happen on iPhone, and doesn't happen on iPadOS 18.5 or below. And removing the 'placement' argument also fixes the issue. NavigationStack { List { /// ... } .searchable( text: $searchText, tokens: $searchTokens, isPresented: $isSearchPresented, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search timestamps" ) { token in Label(token.title, systemImage: token.systemImage) } .searchSuggestions { ForEach(suggestedTokens) { token in Label(token.title, systemImage: token.systemImage) .searchCompletion(token) } } .toolbar { ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } I have a test sample app with this, and created FB22639453 The same problem happens in UIKit as well, when using UISearchController with UINavigationItems' searchController.
Replies
1
Boosts
0
Views
137
Activity
Apr ’26
SF Symbols .replace animation is partially missing
In SF Symbols 7, I'm observing a discrepancy between the .replace animation previewed in the SF Symbols app and the result when using the code template the app provides. Expected behavior: When previewing the .replace animation in the SF Symbols app (with Magic Replace preferred), the transition looks like: Actual behavior: When I implement the animation using the exact code template generated by the SF Symbols app, the result looks like: My code: struct PlaygroundSwiftUIView: View { @State var name = "folder.circle" var body: some View { Image(systemName: name) .font(.system(size: 60)) .contentTransition(.symbolEffect(.replace)) .onTapGesture { name = "tree" } } } #Preview { PlaygroundSwiftUIView() } The animation rendered in my app does not match the preview shown in the SF Symbols app. The drawOff animation is partially missing. Is there something missing from the code template, or is there an additional configuration step required to achieve the correct Replace effect? or is this a bug?
Replies
2
Boosts
0
Views
274
Activity
3w
SF Symbols .replace animation is weird
In SF Symbols 7, I'm observing a discrepancy between the .replace animation previewed in the SF Symbols app and the result when using the code template the app provides. Expected behavior: When previewing the .replace animation in the SF Symbols app (with Magic Replace preferred), the transition looks like: Actual behavior: When I implement the animation using the exact code template generated by the SF Symbols app, the result looks like: My code: struct PlaygroundSwiftUIView: View { @State var name = "folder.circle" var body: some View { Image(systemName: name) .font(.system(size: 60)) .contentTransition(.symbolEffect(.replace)) .onTapGesture { name = "tree" } } } #Preview { PlaygroundSwiftUIView() } The animation rendered in my app does not match the preview shown in the SF Symbols app. The drawOff animation is partly missing. Is there something missing from the code template, or is there an additional configuration step required to achieve the correct Replace effect?
Replies
0
Boosts
0
Views
138
Activity
Apr ’26
Can contextMenu respect onLongPressGesture of a child element?
Hi, I have a list cell with a play button and a text label. When tapping the play button, it plays an audio, and when long-pressed, it plays the audio slowly. The long press works as per the example code below, but once a contextMenu is added, the long-press gesture of the play button is ignored (even though it's a small element in the cell), and the context menu is presented instead. Is there a way to allow for the context menu long-press to respect the long-press gesture of a child element in the cell on which it's defined? I also tried with highPriorityGesture but to no effect. Example code: HStack { Button { print("Play") } label: { Image(systemName: "play.circle") .onLongPressGesture(minimumDuration: 0.5) { print("Play slowly") } } Text("Audio cell") .frame(maxWidth: .infinity, alignment: .leading) } .contextMenu { Button("Hello") { print("hello") } Button("Goodbye") { print("goodbye") } }
Replies
0
Boosts
0
Views
117
Activity
Apr ’26
.buttonStyle(.glass) background changes abruptly between 50pt and 51pt in dark mode
[Submitted as FB22612121] A SwiftUI Button using .buttonStyle(.glass) with .buttonBorderShape(.capsule) changes its background abruptly when its size goes from 50×50 to 51×51 points in dark mode. This appears to be a threshold in opacity/material rather than a smooth size-based change. The sample shows identical buttons at 40, 50, 51, and 60 points, with a clear jump between 50 and 51. Measured RGB values shift from 19,19,19 to 30,30,30. The effect also varies with the background, which points to a material/opacity change rather than a fixed fill. ENVIRONMENT iOS 26.4.1 (23E254a) iOS 26.5 (23F5059e) REPRO STEPS Create a new iOS SwiftUI project. Replace ContentView with the sample code below. Run the app or open ContentView in SwiftUI Preview (dark mode). Observe the buttons at 40×40, 50×50, 51×51, and 60×60. Compare the 50pt and 51pt buttons. ACTUAL The background changes abruptly between 50pt and 51pt. The 51pt button uses a noticeably different opacity/material, producing a visible jump in dark mode. EXPECTED The glass background should remain visually consistent or change smoothly as size changes by 1 point. 50pt and 51pt buttons should not have a discontinuous difference. SCREENSHOT SAMPLE CODE struct ContentView: View { private let sizes: [CGFloat] = [40, 50, 51, 60] var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { Text("Glass button dark-mode size jump") .font(.headline) Text("All buttons use .buttonStyle(.glass). Only the label frame changes.") .font(.footnote) .foregroundStyle(.secondary) ForEach(Array(sizes.enumerated()), id: \.offset) { index, size in HStack(spacing: 14) { Button { } label: { Text("\(index + 1)") .font(.system(size: size * 0.42, weight: .medium)) .frame(width: size, height: size) } .buttonStyle(.glass) .buttonBorderShape(.capsule) Text("label frame: \(Int(size)) x \(Int(size))") .font(.callout.monospacedDigit()) .foregroundStyle(.secondary) } } } .padding(24) } .preferredColorScheme(.dark) } }
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
0
Views
232
Activity
May ’26
How to Indicate Selected State for a Menu Toolbar Item (Filter) in SwiftUI?
hi, On my page’s toolbar, I have a toolbar item that is implemented as a menu. Its purpose is to filter the content displayed on the page, similar to the filtering feature in the Photos app. When a user selects a filter option, I want the toolbar item to appear highlighted to indicate the active state. I came across the following guidance in the Human Interface Guidelines: Provide a selected-state version of an interface icon only if necessary. You don’t need to provide selected and unselected appearances for an icon that’s used in standard system components such as toolbars, tab bars, and buttons. The system updates the visual appearance of the selected state automatically. An image of two toolbar buttons that share a background. The left button shows the Filter icon in a selected state, using a blue tint color for its background. The right button shows the More icon in an unselected state, using the default appearance for toolbar buttons. In a toolbar, a selected icon receives the app’s accent color. However, I’m not sure how to actually implement or control the selected state for my toolbar item. Here is a snippet of my code: ToolbarItem(placement: .topBarTrailing) { Menu { Section { LayoutPickerView(layoutOption: $layoutOption) } Section { SortPickerView(sortOption: $viewModel.sortOption) } Section { Menu { Toggle( isOn: Binding( get: { viewModel.filterPlatforms.isEmpty }, set: { if $0 { viewModel.filterPlatforms.removeAll() } } ) ) { HStack { Image(systemName: "square.grid.3x3") .resizable() .scaledToFit() .frame(width: 30, height: 30) Text(Localized.Content.filterAllPlatforms) } } .menuActionDismissBehavior(.disabled) Divider() ForEach(viewModel.availablePlatforms(from: contents)) { platform in Toggle(isOn: viewModel.platformBinding(for: platform)) { HStack { CachedPlatformIconView(urlString: platform.iconUrl, size: 30) Text(platform.name) } } .menuActionDismissBehavior(.disabled) } } label: { Text(Localized.Content.filterMenu) Text(viewModel.filterPlatforms.map(\.name).joined(separator: String(localized: Localized.Content.separator))) } if !viewModel.filterPlatforms.isEmpty { Button { viewModel.filterPlatforms.removeAll() } label: { Text(Localized.Content.filterClear) } } } } label: { Image(systemName: "line.3.horizontal.decrease") } }
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
139
Activity
Apr ’26
How to detect if a binding is from a state or a constant?
Hi, I'm trying to create a custom TextField component where we can have our own custom FormatStyle as a param and then it will change the value binding according to the FormatStyle. It worked with State<Any?> like for example $textValue. But when I use .constant(2000) for instance, the Formatting doesn't work. So is there any way to detect whether the value param is constant or not? Thank you.
Replies
0
Boosts
0
Views
241
Activity
Apr ’26
Is there an event if the user pops a template with the backbutton
I want to clear certain state when closing a template when the user clicks the backbutton
Replies
0
Boosts
0
Views
88
Activity
Apr ’26
SwiftUI Text rendering with too small height / one line missing causing unexpected text truncation on iPhone devices
FB: FB22577211 The following trivial SwiftUI Text rendering causes wrong text layout and truncated text. The text should take the required height to render the text without truncation. Adding fixedSize does also not solve this. This bug only happens on devices and not on the simulator. Confirmed with iPhone 15 and iOS 26.4.1 but my colleague used another iPhone so it’s multiple iPhone devices. import SwiftUI let txt = """ Es sollte die erste Japan-Tournee von vielen werden, kein anderes Land – abgesehen von Österreich und der Schweiz – bereisten die Berliner Philharmoniker häufiger. Wie kam es zu dem überschäumend herzlichen Empfang, der dem Orchester bei seinem ersten Gastspiel in Tokio bereitet wurde und wie wurde das Land zu einer »zweiten Heimat« für die Berliner? Ein konkreter historischer Grundstein für das hohe Ansehen klassischer Musik »made in Germany« in Japan wurde bereits im 19. Jahrhunderts gelegt: Als Teil von umfassenden gesellschaftlichen Modernisierungsmaßnahmen vergab die Regierung ab 1868 Stipendien an junge japanische Intellektuelle, damit diese an den besten internationalen Instituten studieren konnten. Berlin wurde – neben Wien – als globales Zentrum der Musik betrachtet, und so erhielten viele japanische Studierende um die Jahrhundertwende die Gelegenheit, von Komponisten wie etwa Max Bruch zu lernen. Zurück in der Heimat, teilten sie ihre Begeisterung für die europäische Kunstmusik sowie das Wissen um die instrumentale und kompositorische Praxis der klassisch-romantischen Tradition. """ struct ContentView: View { var body: some View { VStack { Text(txt) } .padding(.leading, 20) .padding(.trailing, 20) .frame(maxWidth: .infinity) } } This is also enough: Text(txt) .padding(.horizontal, 20) .fixedSize(horizontal: false, vertical: true) Expected: Text is rendered without truncation / ellipsis. Actual: Text is rendered with too small height / missing one line so it’s truncated / with ellipsis.
Replies
10
Boosts
0
Views
660
Activity
May ’26
segmented picker style causes runtime warning
On OSX, using a segmented picker style causes the following warning to be emitted (when a different selection is made) : "Publishing changes from within view updates is not allowed, this will cause undefined behavior." The warning is not emitted using the 'Preview Canvas' only when running the app. Changing the picker style to automatic also fixes it, but the segmented style is used extensively. Tested using XCode 26.4.1 on MacOS 26.3.1 --- view --- import SwiftUI internal import Combine enum Mode : String { case one, two, three } class MyObject : ObservableObject { @Published var mode : Mode = .one } struct ContentView: View { @StateObject var obj = MyObject() var body: some View { VStack { Picker("Mode",selection: $obj.mode) { Text("One").tag(Mode.one) Text("Two").tag(Mode.two) Text("Three").tag(Mode.three) } .pickerStyle(.segmented) } .padding() } } #Preview { ContentView() } --- app --- import SwiftUI @main struct SwiftUIBugApp: App { var body: some Scene { WindowGroup { ContentView() } } }
Replies
6
Boosts
0
Views
117
Activity
Apr ’26
Apple Watch Complication with SF Symbols slightly off-center
I have some simple circular complications, that use a ZStack with SFSymbols. On high contrast Watch Faces, I noted that the circle is slightly off to the top leading side. I tried to set the ZStack alignment to center, fiddled around with Spacers, but I could not get it centered. Is that a bug or am I missing something? struct CircularWidgetDashed: View { var entry: Provider.Entry var body: some View { ZStack { Image(systemName: "circle.dashed") .resizable() .scaledToFit() .foregroundColor(.green) Text("\(entry.online)/\(entry.total)") .foregroundStyle(.primary) .font(.caption) .fontWeight(.semibold) } .widgetAccentable() } }
Replies
4
Boosts
0
Views
259
Activity
Apr ’26
SearchFieldPlacement.navigationBarDrawer in NavigationSplitView detail ignores sidebar width on first rendering.
When a NavigationSplitView detail column shows a View that uses .searchable(text: $searchText, placement: .navigationBarDrawer), the search bar extends under the sidebar region, on the first View render only. After any event that triggers a View refresh (such as switching away and back to the View, editing the search text, or resizing the window) the search field is positioned correctly in the detail column’s navigation area. var body: some View { NavigationSplitView { List { Text("Sidebar") } .navigationTitle("Sidebar") } detail: { Text("Detail") .navigationTitle("List") .searchable( text: $searchText, placement: .navigationBarDrawer ) } } FB22559713 has been opened.
Replies
0
Boosts
0
Views
118
Activity
Apr ’26