I sometimes use Xcode 14.2.
Recently, I have an issue with simulators:
on some SwiftUI project, the simulator list is empty.
I created a new project. I see the complete list of simulators, but when running for a simulator, it fails with following diag;
Same error with UIKit project.
Details
Unable to boot the Simulator.
Domain: NSPOSIXErrorDomain
Code: 60
Failure Reason: launchd failed to respond.
User Info: {
DVTErrorCreationDateKey = "2025-06-29 06:16:35 +0000";
IDERunOperationFailingWorker = "_IDEInstalliPhoneSimulatorWorker";
Session = "com.apple.CoreSimulator.SimDevice.134EC197-BA6B-45DF-B5B2-61A1D4F14863";
}
--
Failed to start launchd_sim: could not bind to session, launchd_sim may have crashed or quit responding
Domain: com.apple.SimLaunchHostService.RequestError
Code: 4
--
Analytics Event: com.apple.dt.IDERunOperationWorkerFinished : {
"device_model" = "iPhone15,2";
"device_osBuild" = "16.2 (20C52)";
"device_platform" = "com.apple.platform.iphonesimulator";
"launchSession_schemeCommand" = Run;
"launchSession_state" = 1;
"launchSession_targetArch" = "x86_64";
"operation_duration_ms" = 8341;
"operation_errorCode" = 60;
"operation_errorDomain" = NSPOSIXErrorDomain;
"operation_errorWorker" = "_IDEInstalliPhoneSimulatorWorker";
"operation_name" = IDERunOperationWorkerGroup;
"param_consoleMode" = 0;
"param_debugger_attachToExtensions" = 0;
"param_debugger_attachToXPC" = 1;
"param_debugger_type" = 3;
"param_destination_isProxy" = 0;
"param_destination_platform" = "com.apple.platform.iphonesimulator";
"param_diag_MainThreadChecker_stopOnIssue" = 0;
"param_diag_MallocStackLogging_enableDuringAttach" = 0;
"param_diag_MallocStackLogging_enableForXPC" = 1;
"param_diag_allowLocationSimulation" = 1;
"param_diag_checker_tpc_enable" = 1;
"param_diag_gpu_frameCapture_enable" = 0;
"param_diag_gpu_shaderValidation_enable" = 0;
"param_diag_gpu_validation_enable" = 0;
"param_diag_memoryGraphOnResourceException" = 0;
"param_diag_queueDebugging_enable" = 1;
"param_diag_runtimeProfile_generate" = 0;
"param_diag_sanitizer_asan_enable" = 0;
"param_diag_sanitizer_tsan_enable" = 0;
"param_diag_sanitizer_tsan_stopOnIssue" = 0;
"param_diag_sanitizer_ubsan_stopOnIssue" = 0;
"param_diag_showNonLocalizedStrings" = 0;
"param_diag_viewDebugging_enabled" = 1;
"param_diag_viewDebugging_insertDylibOnLaunch" = 1;
"param_install_style" = 0;
"param_launcher_UID" = 2;
"param_launcher_allowDeviceSensorReplayData" = 0;
"param_launcher_kind" = 0;
"param_launcher_style" = 0;
"param_launcher_substyle" = 0;
"param_runnable_appExtensionHostRunMode" = 0;
"param_runnable_productType" = "com.apple.product-type.application";
"param_runnable_type" = 2;
"param_testing_launchedForTesting" = 0;
"param_testing_suppressSimulatorApp" = 0;
"param_testing_usingCLI" = 0;
"sdk_canonicalName" = "iphonesimulator16.2";
"sdk_osVersion" = "16.2";
"sdk_variant" = iphonesimulator;
}
--
System Information
macOS Version 12.7.1 (Build 21G920)
Xcode 14.2 (21534) (Build 14C18)
Timestamp: 2025-06-29T08:16:35+02:00
I filed a bug report: FB18475006
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I am trying to create a radio group picker in SwiftUI, similar to this:
https://www.neobrutalism.dev/docs/radio-group
I already have a working view based version here:
https://github.com/rational-kunal/NeoBrutalism/blob/main/Sources/NeoBrutalism/Components/Radio/Radio.swift
Now I want to replace it with a more concise/swifty way of Picker with PickerStyle API:
However, I can't find any official documentation or examples showing how to implement PickerStyle. Is it possible to create my own PickerStyle? If not, what’s the recommended alternative to achieve a radio‑group look while still using Picker?
struct NBRadioGroupPickerStyle: PickerStyle {
static func _makeView<SelectionValue>(value: _GraphValue<_PickerValue<NBRadioGroupPickerStyle, SelectionValue>>, inputs: _ViewInputs) -> _ViewOutputs where SelectionValue : Hashable {
<#code#>
}
static func _makeViewList<SelectionValue>(value: _GraphValue<_PickerValue<NBRadioGroupPickerStyle, SelectionValue>>, inputs: _ViewListInputs) -> _ViewListOutputs where SelectionValue : Hashable {
<#code#>
}
}
Crossposting: https://forums.swift.org/t/how-can-i-build-a-custom-pickerstyle-in-swiftui/80755
The default behavior on UIScrollView is that "canCancelContentTouches" is true.
If you add a UIButton to a UICollectionViewCell and then scroll (drag) the scroll view with a touch beginning on that button in that cell, it cancels ".touchUpInside" on the UIButton.
However, if you have a Button in a SwiftUI view configured with "contentConfiguration" it does not cancel the touch, and the button's action is triggered if the user is still touching that cell when the scroll (drag) completes.
Is there a way to forward the touch cancellations to the SwiftUI view, or is it expected that all interactivity is handled only in UIKit, and not inside of "contentConfiguration" in specific cases? This behavior seems to occur on all SwiftUI versions supporting UIHostingConfiguration so far.
I made a small project that freezes after the following steps:
Run the app
Turn on VoiceOver
Tap on "Header" once so it is read out loud
Turn off VoiceOver
Scroll up and down really quickly
Using the Time Profiler, the items in the Main Thread followed by significant drops are:
19.11 s 85.1% 0 s closure #2 in closure #1 in ViewRendererHost.render(interval:updateDisplayList:targetTimestamp:)
13.05 s 58.1% 4.00 ms ViewGraph.updateOutputs(async:)
7.97 s 35.5% 83.00 ms AG::Graph::UpdateStack::update()
5.76 s 25.6% 19.00 ms LayoutScrollableTransform.updateValue()
1.73 s 7.7% 2.00 ms specialized NativeDictionary.setValue(:forKey:isUnique:)
579.00 ms 2.6% 58.00 ms 0x100a8c908
311.00 ms 1.4% 165.00 ms __thread_stack_pcs
I see the memory usage increase by about 0.6 MB per second while frozen.
And there are a few things that prevent the freeze:
Changing LazyVStack for VStack
Removing the VStack from the Section
Removing the header: parameter from the Section
Reducing the range of the ForEach
Move the Text(verbatim: "Text at same level as ForEach containing Section") outside of the LazyVStack
However, these are all things I need to keep for my actual app. So what is causing this hang? Am I using SwiftUI in any way it's not intended to be used?
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
VStack(alignment: .leading) {
Image(systemName: "pencil.circle.fill")
Text("Title")
Text("Label")
}
ScrollView {
LazyVStack {
Section {
VStack {
ForEach(0..<70) { _ in
Text(verbatim: "A")
}
}
} header: {
Text(verbatim: "Header")
}
Text(verbatim: "Text at same level as ForEach containing Section")
}
}
}
}
}
AppDelegate:
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UINavigationController(rootViewController: MainViewController())
window.makeKeyAndVisible()
self.window = window
return true
}
}
MainViewController:
import UIKit
import SwiftUI
final class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let swiftUIView = ContentView()
let hostingController = UIHostingController(rootView: swiftUIView)
addChild(hostingController)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(hostingController.view)
NSLayoutConstraint.activate([
hostingController.view.topAnchor.constraint(equalTo: view.topAnchor),
hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
hostingController.didMove(toParent: self)
view.backgroundColor = .white
}
}
Hello there, I ran into a very strange layout issue in SwiftUI. Here's the View:
struct OnboardingGreeting: View {
/// ...
let carouselSpacing: CGFloat = 7
let carouselItemSize: CGFloat = 110
let carouselVelocities: [CGFloat] = [0.5, -0.25, 0.3, 0.2]
var body: some View {
ZStack(alignment: Alignment(horizontal: .center, vertical: .iconToCarouselBottom)) {
VStack(spacing: carouselSpacing) {
ForEach(carouselVelocities, id: \.self) { velocityValue in
InfiniteHorizontalCarousel(
albumNames: albums,
artistNames: artists,
itemSize: carouselItemSize,
itemSpacing: carouselSpacing,
velocity: velocityValue
)
}
}
.alignmentGuide(.iconToCarouselBottom) { context in
context[VerticalAlignment.bottom]
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top)
LinearGradient(
colors: [.black, .clear],
startPoint: .bottom,
endPoint: .top
)
// Top VStack
VStack(spacing: 0) {
RoundedRectangle(cornerRadius: 18)
.fill(.red)
.frame(width: 95, height: 95)
.alignmentGuide(.iconToCarouselBottom) { context in
context.height / 2
}
Text("Welcome to Music Radar!")
.font(.title)
.fontDesign(.serif)
.bold()
Text("Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum Lorem Impsum")
.font(.body)
.fontDesign(.serif)
PrimaryActionButton("Next") {
// navigate to the next screen
}
.padding(.horizontal)
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}
.ignoresSafeArea(.all, edges: .top)
.statusBarHidden()
}
}
extension VerticalAlignment {
private struct IconToCarouselBottomAlignment: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
context[VerticalAlignment.center]
}
}
static let iconToCarouselBottom = VerticalAlignment(
IconToCarouselBottomAlignment.self
)
}
At this point the view looks like this:
I want to push the Button in the Top VStack to the bottom of the screen and the red rounded rectangle to stay pinned to the bottom of the horizontal carousel (hence the custom alignment guide being introduced). The natural solution would be to add the Spacer(). However, for some reason when I do it, it results in the button going all the way down to outside of the screen, which means that the bottom safe area isn't being respected. Using the alignment parameter in the flexible frame also doesn't work the way I want it to. I suspect that custom alignment guide can cause this behavior but I can't find the way to fix it. Help me out, please.
I Implement a 'SubscriptionStoreView' using 'groupID' into a project (iOS is targeting 17.2 and macOS is targeting 14.1).Build/run the application locally (both production and development environments will work fine), however once the application is live on the AppStore in AppStoreConnect, SubscriptionStoreView no longer shows products and only shows 'Subscription Unavailable' and 'The subscription is unavailable in the current storefront.' - this message is shown live in production for both iOS and macOS targets. There is no log messages shown in the Console that indicate anything going wrong with StoreKit 2, but I haven't made any changes to my code and noticed this first start appearing about 5 days ago.
I expect the subscription store to be visible to all users and for my products to display. My application is live on both the iOS and macOS AppStores, it passed App Review and I have users who have previously been able to subscribe and use my application, I have not pushed any new changes, so something has changed in StoreKit2 which is causing unexpected behaviour and for this error message to display. As 'SubscriptionStoreView' is a view provided by Apple, I'm really not sure on the pathway forward other than going back to StoreKit1 which I really don't want to do.
Is there any further error information that can be provided on what might be causing this and how I can fix it? (I have created a feedback ticket FB13658521)
While editing the search text using the external keyboard (with VoiceOver on), if I try to navigate the to List using the keyboard, the focus jumps back to the search field immediately, preventing selection of list items. It's important to note that the voiceover navigation alone without a keyboard works as expected.
It’s as if the List never gains focus—every attempt to move focus lands back on the search field.
The code:
struct ContentView: View {
@State var searchText = ""
let items = ["Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig", "Grape"]
var filteredItems: [String] {
if searchText.isEmpty {
return items
} else {
return items.filter { $0.localizedCaseInsensitiveContains(searchText) }
}
}
var body: some View {
if #available(iOS 16.0, *) {
NavigationStack {
List(filteredItems, id: \.self) { item in
Text(item)
}
.navigationTitle("Fruits")
.searchable(text: $searchText)
}
} else {
NavigationView {
List(filteredItems, id: \.self) { item in
Text(item)
}
.navigationTitle("Fruits")
.searchable(text: $searchText)
}
}
}
}
Starting in visionOS 26, users can snap windows to surfaces. These windows are locked in place and are later restored by visionOS. We can access the snapped data with surfaceSnappingInfo docs.
Users can also lock a free-floating (unsnapped) window from a context menu in the window controls.
Is there a way to tell when a window has been locked without being snapped to a surface?
hi everyone, any thought on how to implement a RichText(markdown) live editor using the new TextEditor(text: AttributedString, selection: AttributedTextSelection)?
Having issues like:
how to get the location of the selected text relatived to the TextEditor bounds, which is used to show and position a floating toolbar.
how to detect the cursor point is a new line and the content is "# ", (of couse now the user enter a space after the "#"), and if so, how to apply a H1 heading format to that line
much more issues like this, but these two are how to get me started, thanks
struct TextEditor8: View {
@State var text: AttributedString
@State var selection = AttributedTextSelection()
@State var isShowFloatingToolbar = false
@State var toolbarPosition: CGPoint = .zero
init() {
var text = AttributedString("Hello ✋🏻,Who is ready for Cooking?")
let range = text.characters.indices(where: \.isUppercase)
text[range].foregroundColor = .blue
_text = State(initialValue: text)
}
var body: some View {
ZStack(alignment: .topLeading) {
GeometryReader { geo in
TextEditor(text: $text, selection: $selection)
.onChange(of: selection, perform: { newV in
let v = text[newV]
if v.characters.isEmpty {
isShowFloatingToolbar = false
} else {
isShowFloatingToolbar = true
toolbarPosition = CGPoint(x: 20, y: 20) // how to get CGPoint relatived to TextEditor from selection
}
print("vvvv", v.characters.isEmpty)
})
}
if isShowFloatingToolbar {
FloatingToolbarAtSelection()
.position(toolbarPosition)
}
}
}
}
With the new @Observable macro, it looks like every time the struct of a view is reinitialized, any observable class marked as @State in the struct also gets reinitialized. Moreover, the result of the reinitialization immediately gets discarded.
This is in contrast to @StateObject and ObservableObject, where the class would only be initialized at the first creation of the view. The initialization method of the class would never be called again between view updates.
Is this a bug or an expected behavior? This redundant reinitialization causes performance issues when the init method of the observable class does anything slightly heavyweight.
Feedback ID: FB13697724
Hi,
I'm trying to create a custom bottom toolbar for my app and want to use same fade-blur effect as iOS uses under navigation and tab bars. Having trouble doing that.
Here is what I tried:
Screenshot 1: putting my custom view in a toolbar/ToolBarItem(placement: .bottomBar). This works only in NavigationStack, and it adds a glass pane that I do not want (I want to put a custom component there that already has correct glass pane)
Screenshot 2: using safeAreaBar or safeAreaInset in any combination with NavigationStack and/or .scrollEdgeEffectStyle(.soft, for: .bottom). Shows my component correctly, but does not use fade-blur.
Can you please help me to find out the correct way of doing that? Thanks!
^ Screenshot 1
^ Screenshot 2
Test code:
struct ContentView2: View {
var body: some View {
NavigationStack {
ScrollView(.vertical) {
VStack {
Color.red.frame(height: 500)
Color.green.frame(height: 500)
}
}
.ignoresSafeArea()
.toolbar() {
ToolbarItem(placement: .bottomBar) {
HStack {
Text("bottom")
Spacer()
Text("text content")
}
.bold().padding()
.glassEffect().padding(.horizontal)
}
}
}
}
}
Hi all,
I’m trying to implement a collapsible section in a List on watchOS (watchOS 10+). The goal is to have a disclosure chevron that toggles a section open/closed with animation, similar to DisclosureGroup on iOS.
Unfortunately, DisclosureGroup is not available on watchOS. 😢
On iOS, this works as expected using this Section init:
Section("My Header", isExpanded: $isExpanded) {
// content
}
That gives me a tappable header with a disclosure indicator and the animation built in, as expected.
But on watchOS, this same init displays the header, but it’s not tappable, and no disclosure triangle appears.
I’ve found that to get it working on watchOS, I need to use the other initializer:
Section(isExpanded: $isExpanded) {
// content
} header: {
Button(action: { isExpanded.toggle() }) {
HStack {
Title("My Header")
Spacer()
Image(systemName: isExpanded ? "chevron.down" : "chevron.right")
}
}
That works, but feels like a workaround. Is this the intended approach for watchOS, or am I missing a more native way to do this?
Any best practices or alternative recommendations appreciated.
Thanks!
I just wanted to post this here because since we started using SwiftUI, SwiftUI Previews have been painful to use, and then became basically unusable. And then after many hours of investigating, I seem to have found a solution and I wanted to share it somewhere useful.
The symptoms were that when clicking in the circle to enable preview (from the preview paused state) for any view, the progress spinner would sit there for... sometimes forever, but sometimes for 20 minutes before a preview would show.
It wasn't just slow, it was entirely unusable. Most of the complaints I've seen from other developers are about it being slow and unresponsive, but for us, it would just spin infinitely (rarely it would stop and then the preview would display). None of the 'fixes' here or on StackOverflow, etc helped.
So after a year of just mostly not using SwiftUI Previews, I found something interesting - under the build tab, the app was continually being rebuilt when the preview canvas with the spinner was being shown.
What?
OK, so it turns out we have a Run Script build step that generates output (a Credits.plist for open source libraries). It did not declare output files, which XCode had long complained about, but in general was not an issue... except apparently for SwiftUI Previews.
Checking the "For install builds. only" checkbox for this build step made the problem go away. That was it. SwiftUI Previews build and run fairly well now.
I have not tried fixing the complaint about the build script outputs - that might have also fixed the problem, but "For install builds only" definitely fixed our issue.
I am trying out the new AttributedString binding with SwiftUI’s TextEditor in iOS26. I need to save this to a Core Data database. Core Data has no AttributedString type, so I set the type of the field to “Transformable”, give it a custom class of NSAttributedString, and set the transformer to NSSecureUnarchiveFromData
When I try to save, I first convert the Swift AttributedString to NSAttributedString, and then save the context. Unfortunately I get this error when saving the context, and the save isn't persisted:
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x600003721140> , <shared NSSecureUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
Here's the code that tries to save the attributed string:
struct AttributedDetailView: View {
@ObservedObject var item: Item
@State private var notesText = AttributedString()
var body: some View {
VStack {
TextEditor(text: $notesText)
.padding()
.onChange(of: notesText) {
item.attributedString = NSAttributedString(notesText)
}
}
.onAppear {
if let nsattributed = item.attributedString {
notesText = AttributedString(nsattributed)
} else {
notesText = ""
}
}
.task {
item.attributedString = NSAttributedString(notesText)
do {
try item.managedObjectContext?.save()
} catch {
print("core data save error = \(error)")
}
}
}
}
When using the writingToolsBehavior API on a TextField and the app compiled with the iOS 26 SDK is run on an iOS 18 device, the app crashes with a symbol not found error.
It only crashes on the release build configuration and not on debug.
dyld[5274]: Symbol not found: _$s7SwiftUI17EnvironmentValuesV21_writingToolsBehaviorAA07WritingfG0VSgvg Referenced from: <1306655E-6DF7-3B2A-94A3-7202149E82F3> /private/var/containers/Bundle/Application/88E47904-4884-4279-9E96-0EC366970389/WritingToolsTest.app/WritingToolsTest Expected in: <165D3305-401E-37C2-8387-C1BFB54CFFDE> /System/Library/Frameworks/SwiftUI.framework/SwiftUI
Feedback ID: FB17980516
I am trying out the new AttributedString binding with SwiftUI’s TextEditor in iOS26. I need to save this to a Core Data database. Core Data has no AttributedString type, so I set the type of the field to “Transformable”, give it a custom class of NSAttributedString, and set the transformer to NSSecureUnarchiveFromData
When I try to save, I first convert the Swift AttributedString to NSAttributedString, and then save the context. Unfortunately I get this error when saving the context, and the save isn't persisted:
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x600003721140> , <shared NSSecureUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
Here's the code that tries to save the attributed string:
struct AttributedDetailView: View {
@ObservedObject var item: Item
@State private var notesText = AttributedString()
var body: some View {
VStack {
TextEditor(text: $notesText)
.padding()
.onChange(of: notesText) {
item.attributedString = NSAttributedString(notesText)
}
}
.onAppear {
if let nsattributed = item.attributedString {
notesText = AttributedString(nsattributed)
} else {
notesText = ""
}
}
.task {
item.attributedString = NSAttributedString(notesText)
do {
try item.managedObjectContext?.save()
} catch {
print("core data save error = \(error)")
}
}
}
}
This is the attribute setup in the Core Data model editor:
Is there a workaround for this?
I filed FB17943846 if someone can take a look.
Thanks.
According to this video, in iOS 26 there should be an containerConcentric configuration that can be passed to the corner parameter of a rectangle.
But when trying this on my own, it looks like there is no cornerparameter and also no containerConcentric configuration. Also, I can't find this in the SwiftUI documentation.
.glassProminent not working, but .glass works for .buttonStyle()
as used here
https://youtu.be/3MugGCtm26A?si=dvo2FeE88OnNIwI9&t=938
/Users/brianruiz/repos/taskss/taskss/Views/Components/EmptyStateView.swift:125:39 Reference to member 'glassProminent' cannot be resolved without a contextual type
if #available(iOS 26.0, *) {
Button(action: {
HapticManager.shared.selection()
action()
}) {
Text(buttonLabel ?? "Action")
.frame(maxWidth: .infinity)
}
.padding(.horizontal, 24)
.buttonStyle(.glassProminent)
.buttonBorderShape(.capsule)
.controlSize(.large)
.tint(.primary)
.offset(y: buttonOffset)
.opacity(buttonOpacity)
.scaleEffect(isPressed ? 0.95 : 1.0)
.animation(.bouncy(), value: isPressed)
.onLongPressGesture(minimumDuration: .infinity, maximumDistance: 50, pressing: { pressing in
isPressed = pressing
}, perform: {})
.onAppear {
guard animate else { return }
withAnimation(.bouncy().delay(0.6)) {
buttonOffset = 0
buttonOpacity = 1
}
}
} else {
// Fallback on earlier versions
}
Hi, has anyone noticed that when using SwiftUI the MapKit Marker created with
Marker(item: MKMapItem)
.tint(.red) //solid flat color
ignores the default marker styling (the nice gradient and shadow) and shows only a flat solid fill?
The shadow/gradient appears correctly with some colors like .blue or .orange, but disappears with others such as .red, .purple, etc.
What’s odd is that this happens only with the init(item: MKMapItem) initializer. A marker created with, for example, following init works just fine.
Marker("hello", coordinate: CLLocationCoordinate2D)
.tint(.red) //nice shadow/gradient
Is this a bug, or does a marker backed by an MKMapItem support only a limited color range? (If so, exposing .tint there seems inconsistent—either all colors should work or none.)
Has anyone else run into this problem?
.orange with shadow/gradient:
.red solid without shadow/gradient:
There is an issue with SwiftUI where it is incorrectly instantiating the navigation destination view with a new identity for a navigation stack that is being removed.
Here is a minimal reproducible example:
struct ContentView: View {
@State private var signedIn = false
var body: some View {
if signedIn {
navigationStack(isSignedIn: true)
} else {
navigationStack(isSignedIn: false)
}
}
private func navigationStack(isSignedIn: Bool) -> some View {
NavigationStack(path: .constant(NavigationPath([1]))) {
EmptyView()
.navigationDestination(for: Int.self) { _ in
VStack {
Text(isSignedIn ? "Signed In" : "Signed Out")
.foregroundStyle(Color.red)
Button(isSignedIn ? "Sign Out" : "Sign In") {
signedIn = !isSignedIn
}
}
.onFirstAppear {
print(isSignedIn ? "signed in" : "signed out")
}
}
}
}
}
struct OnFirstAppearView: ViewModifier {
@State private var hasAppeared = false
var onAppear: () -> Void
func body(content: Content) -> some View {
content
.onAppear {
if hasAppeared { return }
hasAppeared = true
onAppear()
}
}
}
extension View {
func onFirstAppear(_ onAppear: @escaping () -> Void) -> some View {
ModifiedContent(content: self, modifier: OnFirstAppearView(onAppear: onAppear))
}
}
When you launch the app it will print "signed out", but when you tap to Sign In it will print "signed out" and "signed in". This shows that onAppear is incorrectly being called for a view that is disappearing and worse yet, it is with a new identity.
The onFirstAppear modifier was created to help with detecting the identity change of the view.
Tested on Xcode 16.4, on simulator using iOS 18.5 and also on physical device using iOS 18.5.
Link to Feedback sent on Feedback Assistant: https://feedbackassistant.apple.com/feedback/18336684