I'm running into a weird SwiftUI concurrency issue that only seems to happen on a real device (iOS 18.5 in my case), and not in simulator. I have a NavigationSplitView where the Detail view uses .task(id:_:) to perform some async work upon appearance (in my real-world case, a map snapshot). When running this on a real device, the first execution of the task works as expected. However, any task subsequent executions, even ones for the same id, always start in the Task.isCancelled state.
Is there something about .task(id:_:) that I'm misunderstanding, or have I stumbled upon a serious bug here?
import SwiftUI
struct ContentView: View {
var body: some View {
TaskBugSplitView()
}
}
struct TestItem: Identifiable, Hashable {
var id: Int
var name: String
}
struct TaskBugSplitView: View {
@State
private var selectedItemIndex: [TestItem].Index?
@State
private var testItems: [TestItem] = [
TestItem(id: 1, name: "First Item"),
TestItem(id: 2, name: "Second Item"),
TestItem(id: 3, name: "Third Item"),
TestItem(id: 4, name: "Fourth Item"),
TestItem(id: 5, name: "Fifth Item")
]
var body: some View {
NavigationSplitView {
List(testItems.indices, id: \.self, selection: $selectedItemIndex) { item in
Text(testItems[item].name)
}
} detail: {
if let selectedItemIndex {
TaskBugDetailView(item: testItems[selectedItemIndex])
} else {
Text("Select an item")
.foregroundStyle(.secondary)
}
}
}
}
struct TaskBugDetailView: View {
@State var item: TestItem
@State private var taskResult = "Not started"
var body: some View {
VStack(spacing: 20) {
Text("Item: \(item.name)")
.font(.title2)
Text("Task Result:")
.font(.headline)
Text(taskResult)
.foregroundStyle(taskResult.contains("CANCELLED") ? .red : .primary)
Spacer()
}
.padding()
.navigationTitle(item.name)
.task(id: item.id) {
// BUG: On real devices, Task.isCancelled is true immediately for all tasks
// after the first successful one, even though the ID has changed
if Task.isCancelled {
taskResult = "CANCELLED at start"
print("Task cancelled at start for item \(item.id)")
return
}
taskResult = "SUCCESS"
print("Task completed successfully for item \(item.id)")
}
}
}
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
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?
One of the bar button items of my bottom toolbar needs to be a custom view., and I’m trying hard to get it to behave like the proper bar button items when it comes to Liquid Glass and matching the appearance of all the other bar button items on my toolbar. I’ve tried many variations of embedding custom views within visual effect views, and this comes closest.
I inited a UIBarButtonItem with a custom UIView like you’re supposed to, and then I placed a UIVisualEffectView with Vibrancy within that, so that I could place a UIImageView inside it and the UIImageView would respect the adaptive color changing that comes with being within a Liquid Glass bar button item. I’ve made sure that the UIImageView is using an SF Symbol and a rendering mode of .alwaysTemplate, and that the .tintColor is set to .label, to ensure that I’m not overriding any Liquid Glass rendering.
Below, you can see the bar button item with my custom view on the left, and a native Bar Button Item with the same SF symbol on the right, in several scenarios. It gets part of the way there there: against light backgrounds the image view turns black like it should. But against darker backgrounds, instead of turning white, the symbol has an additional vibrancy that comes close to the right white look against certain grays, but then is obviously too translucent against black.
The symbol is still visible/experiencing some vibrancy, so I assume it might be some configuration of the UIImageView within the Vibrancy that can correct the behavior to match the images in the native bar button items in all conditions. Anyone got thoughts on what the missing piece might be?
I'm working on the control widget which should display the SF image on the UI, but I have found that it cannot be displayed stably. I have eight CarCtrlWidgets which is about the type doorLock、chargeCover、frontBox、 locateCarLight、 locateCarHorn、 ventilate、 backBox and airCondition, it should all be showed but sometime they only show the text and placeholder. I'm aware of the images should be custom SF image and I can see them to show perfectly sometimes, but in other time it is just failed. This's really confused me, can anyone help me out?
deviceversion 18.5;device model iPhone 16 pro;
My sample app has been working with the following code:
func call(arguments: Arguments) async throws -> ToolOutput {
var temp:Int
switch arguments.city {
case .singapore: temp = Int.random(in: 30..<40)
case .china: temp = Int.random(in: 10..<30)
}
let content = GeneratedContent(temp)
let output = ToolOutput(content)
return output
}
However in 26 beta 5, ToolOutput no longer available, please advice what has changed.
I’m trying to use the new safeAreaBar() to place a button in the bottom safe area of the view for the main action. However, there’s a bug when the view is inside a NavigationStack: a white or translucent background appears around the button. When I move the view outside of the NavigationStack, the issue goes away.
NavigationStack {
List {
Text("ok")
}
.safeAreaBar(edge: .bottom) {
Button(action: {}, label: {
Text("Continue").font(.headline)
})
.buttonStyle(.glassProminent)
}
}
Is it a known issue?
I'm working with an app that has a structure of a main TabView, where each Tab has its own NavigationStack. A very simplified rendition of the app looks like this:
struct ContentView: View {
var body: some View {
TabView {
Tab("Tab 1", systemImage: "document") {
NavigationStack {
VStack {
Text("Tab 1")
NavigationLink("Load Detail") {
VStack {
Text("Detail View")
}.toolbarVisibility(.hidden, for: .bottomBar, .tabBar)
}
}
}
}
Tab("Tab 2", systemImage: "map") {
NavigationStack {
VStack {
Text("Tab 2")
}
}
}
}.tabViewBottomAccessory {
Button("Action") {}
}
}
}
With this structure, when I load the detail view in the NavigationLink, I see the tab bar hidden as I would expect. Unfortunately, the tabViewBottomAccessory button remains visible. I've taken some steps to try and fix this ( injecting state at different levels that observe the navigation path and try to change the visibility ) but none of those attempts work, and it seems to me that fundamentally, if the tab bar is desired to be hidden, then so also should the tab accessory be hidden.
I didn't find anywhere online that seemed to indicate this was a known bug, so wanted to post this here first to see if this was the behavior that is expected, or worth filing a bug in iOS 26.
I can't use Xcode without it crashing.
Just writing a very simple iOS app with SwiftUI (using only forms and sections). Whenever my canvas updates to correspond to my changes it forces my Macbook to restart.
Does anyone have a solution for this. I'll be honest it's becoming really frustrating.
Thank you.
Macbook M3 Pro 16GB ram, 500gb Space (400gb free space)
I have an issue with Xcode that it crashes my Macbook and restarts it instantly when I unpause the preview canvas.
I managed to make it run for a minute longer by not watching a youtube video.
I am writing a very simple SwiftUI project for iOS nothing too big to warrant any issues.
Does anyone have a solution to fix this?
Macbook Pro M3 16GB RAM, 500GB SSD (plenty of storage space)
Tahoe 26.0
I made a (very simple) custom tab bar in SwiftUI. It's simply an HStack containing two buttons. These buttons control the selection of a paged TabView. This works well, but in VoiceOver they don't behave like the bottom tab bar or e.g. a segmented picker. Specifically, VoiceOver does not say something like "tab one of two" when the first button is focused.
According to my research, in UIKit this can be accomplished by giving the container view the accessibility trait tabBar, hiding it as an accessibility element and give it the accessibility container type semanticGroup.
In SwiftUI, there is also the trait isTabBar, but that does not seem to have any impact for VoiceOver. I don't see an equivalent of semanticGroup in SwiftUI. I tried accessibilityElement(children: .contain) but that also does not seem to have any impact.
So, is there any way in SwiftUI to make a button behave like a tab-button in VoiceOver? And how is SwiftUI's isTabBar accessibility trait supposed to be used?
I've been experimenting with Liquid Glass quite a bit and watched all the WWDC videos. I'm trying to create a glassy segmented picker, like the one used in Camera:
however, it seems that no matter what I do there's no way to recreate a truly clear (passthrough) bubble that just warps the light underneath around the edges. Both Glass.regular and Glass.clear seem to add a blur that can not be evaded, which is counter to what clear ought to mean.
Here are my results:
I've used SwiftUI for my experiment but I went through the UIKit APIs and there doesn't seem to be anything that suggests full transparency.
Here is my test SwiftUI code:
struct GlassPicker: View {
@State private var selected: Int?
var body: some View {
ScrollView([.horizontal], showsIndicators: false) {
HStack(spacing: 0) {
ForEach(0..<20) { i in
Text("Row \(i)")
.id(i)
.padding()
}
}
.scrollTargetLayout()
}
.contentMargins(.horizontal, 161)
.scrollTargetBehavior(.viewAligned)
.scrollPosition(id: $selected, anchor: .center)
.background(.foreground.opacity(0.2))
.clipShape(.capsule)
.overlay {
DefaultGlassEffectShape()
.fill(.clear) // Removes a semi-transparent foreground fill
.frame(width: 110, height: 50)
.glassEffect(.clear)
}
}
}
Is there any way to achieve the above result or does Apple not trust us devs with more granular control over these liquid glass elements?
as i know, i can add a UIWindowSceneDragInteraction to my view to do this. but how can I achieve the same effect in SwiftUI? Is there a way to do it without relying on UIKit?
How to Hide Unused Menu Items on iPadOS Menu Bar in SwiftUI?
(Xcode 26 beta 4, iPadOS 26 beta 4)
We’re working on adding menu bar support to our SwiftUI app on iPadOS, aiming to provide a more consistent and productive experience across platforms.
We’d like to hide system-provided menu items that aren’t relevant to our app, such as:
Open…
Select All
Customize Toolbar…
New Window, Show All Windows, Open Windows, etc.
Is there a way to control which default items appear in the menu bar?
Feedback ID: FB18792279
How to Enable or Customize Undo/Redo Menu Items on iPadOS Menu Bar in SwiftUI?
(Xcode 26 beta 4, iPadOS 26 beta 4)
We’re working on adding menu bar support to our SwiftUI app on iPadOS, aiming to provide a more consistent and productive experience across platforms.
Our app is a unified iPad/macOS app that uses UndoManager to support undo/redo operations.
However, we’ve run into the following issues:
On macOS, undo and redo work as expected via the menu bar.
On iPadOS, the Undo and Redo menu items are always disabled, even though the functionality works within the app.
We also explored the possibility of hiding the system-generated Undo/Redo menu items so we could provide custom implementations—but couldn’t find a way to remove or override them.
Question:
Is there a recommended approach to enable or customize the Undo/Redo menu bar items on iPadOS using SwiftUI?
Any suggestions or insights would be greatly appreciated!
Feedback ID: FB18792279
How to Support Menu Bar Copy/Paste/Cut/Delete Commands on iPadOS with SwiftUI?
(Xcode 26 beta 4, iPadOS 26 beta 4)
We’re working on adding menu bar support to our SwiftUI app on iPadOS, aiming to provide a more consistent and productive experience across platforms.
However, we’ve encountered a challenge when trying to handle standard editing commands like Copy, Cut, Paste, and Delete from the menu bar:
On iPadOS, SwiftUI modifiers such as onCopyCommand, onCutCommand, onPasteCommand, and onDeleteCommand appear to be unavailable.
Additionally, since we can’t hide or override the default app menus, we’re unsure how to hook into or replace their behavior effectively.
Question:
What’s the recommended way to support standard editing actions like copy/paste via the menu bar in SwiftUI on iPadOS? Are there any workarounds or APIs we might have overlooked?
Any guidance or best practices would be greatly appreciated!
Feedback ID: FB18792279
Hi everyone,
I’m building an iOS app that originally targeted iPhone using NavigationStack. Now I’m adapting it for iPad and switched to using NavigationSplitView to support a three-column layout.
The structure looks like this:
NavigationSplitView {
A // Sidebar
} content: {
B // Middle column – this shows a list
} detail: {
C // Detail view
}
The issue is with the list shown in view B (the content column). It appears completely unstyled, as if it’s using .listStyle(.plain) — with no background material, no grouped sections, and a very flat look.
I can understand that this might be intentional on iPad to visually distinguish the three columns.
However, the problem is that this same unstyled list also appears on iPhone, even though iPhone only shows a single column view at a time!
I tried explicitly setting .listStyle(.insetGrouped) or .listStyle(.grouped) on the list in view B, but it makes no difference.
When I go back to NavigationStack, the list in B is styled properly, just as expected — but then I lose the enhanced iPad layout.
What I’m looking for:
I’d like to keep using NavigationSplitView, but I want the list in the content column (view B) to use the default iOS list styling, at least on iPhone.
Is there any way to achieve this?
Thanks!
Is there a way to constrain the AttributedTextFormattingDefinition of a TextEditor to only bold/italic/underline/strikethrough, without showing the full Font UI?
struct CustomFormattingDefinition: AttributedTextFormattingDefinition {
struct Scope: AttributeScope {
let font: AttributeScopes.SwiftUIAttributes.FontAttribute
let underlineStyle: AttributeScopes.SwiftUIAttributes.UnderlineStyleAttribute
let strikethroughStyle: AttributeScopes.SwiftUIAttributes.StrikethroughStyleAttribute
}
var body: some AttributedTextFormattingDefinition<Scope> {
ValueConstraint(for: \.font,
values: [MyStyle.defaultFont, MyStyle.boldFont, MyStyle.italicFont, MyStyle.boldItalicFont],
default: MyStyle.defaultFont)
ValueConstraint(for: \.underlineStyle,
values: [nil, .single],
default: .single)
ValueConstraint(for: \.strikethroughStyle,
values: [nil, .single],
default: .single)
}
}
If I remove the Font attribute from the scope, the Bold and Italic buttons disappear. And if the Font attribute is defined, even if it's restricted to one typeface in 4 different styles, the full typography UI is displayed.
I am trying to add a pinned(always visible and not moving) toolbar to the bottom of UISheetPresentationController or presentationDetent.
This is achievable when the user is dragging to change the size of the sheet.
But when changing the detent by code, it does not work. For example, when changing from medium to large, the ViewController's size is changed to large then moved up to the position.
From the user's POV, anything at the bottom to disappear for a few frames then reappears.
From my testing, when using UISheetPresentationController, ViewController only knows the medium and large state's frame and bounds, so manually setting it up won't work.
Is there a way to keep views at the bottom always visible in this case?
The sample code below is in SwiftUI for easy recreation, and the responses can be in UIKit.
Sample Code:
struct ContentView: View {
@State var showSheet: Bool = true
@State var detent: PresentationDetent = .medium
var body: some View {
EmptyView()
.sheet(isPresented: $showSheet) {
ScrollView {
}
.safeAreaInset(edge: .bottom) {
Button {
detent = (detent == .medium) ? .large : .medium
} label: {
Text("Change Size")
}
.buttonStyle(.borderedProminent)
.presentationDetents([.medium, .large], selection: $detent)
.presentationBackgroundInteraction(.enabled)
}
}
}
}
[Also submitted as FB19313064]
The .disabled() modifier doesn't visually disable buttons inside a ToolbarItem container on iOS 26.0 (23A5297i) devices. The button looks enabled, but tapping it doesn't trigger the action.
When deployment target is lowered to iOS 18 and deployed to an iOS 18 device, it works correctly. It still fails on an iOS 26 device, even with an iOS 18-targeted build.
This occurs in both the Simulator and on a physical device.
Screen Recording
Code
struct ContentView: View {
@State private var isButtonDisabled = false
private var osTitle: String {
let version = ProcessInfo.processInfo.operatingSystemVersion
return "iOS \(version.majorVersion)"
}
var body: some View {
NavigationStack {
VStack {
Button("Body Button") {
print("Body button tapped")
}
.buttonStyle(.borderedProminent)
.disabled(isButtonDisabled)
Toggle("Disable buttons", isOn: $isButtonDisabled)
Spacer()
}
.padding()
.navigationTitle("Device: \(osTitle)")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem {
Button("Toolbar") {
print("Toolbar button tapped")
}
.buttonStyle(.borderedProminent)
.disabled(isButtonDisabled)
}
}
}
}
}
I have a minimal macOS document based app written in SwiftUI in Xcode 16.3. It is created from the standard template replacing all occurences of 'com.example.plain-text' with 'com.topografix.gpx' and changing the file extension in info.plist from 'exampletext' to 'gpx'.
Those changes are sufficient to allow opening, editing and saving of .gpx files.
However, when opening, editing or saving, the following message is written to the console 6 times.
Unexpected bundle class 16 declaring type public.gpx
While this is not preventing the app from working, I would like to understand the origin of the message and fix the underlying problem.