Post

Replies

Boosts

Views

Activity

tabViewBottomAccessory in 26.1: View's @State is lost when switching tabs
Any view that is content for the tabViewBottomAccessory API fails to retain its state as of the last couple of 26.1 betas (and RC). The loss of state happens (at least) when the currently selected tab is switched (filed as FB20901325). Here's code to reproduce the issue: struct ContentView: View { @State private var selectedTab = TabSelection.one enum TabSelection: Hashable { case one, two } var body: some View { TabView(selection: $selectedTab) { Tab("One", systemImage: "1.circle", value: .one) { BugExplanationView() } Tab("Two", systemImage: "2.circle", value: .two) { BugExplanationView() } } .tabViewBottomAccessory { AccessoryView() } } } struct AccessoryView: View { @State private var counter = 0 // This guy's state gets lost (as of iOS 26.1) var body: some View { Stepper("Counter: \(counter)", value: $counter) .padding(.horizontal) } } struct BugExplanationView: View { var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { Text("(1) Manipulate the counter state") Text("(2) Then switch tabs") Text("BUG: The counter state gets unexpectedly reset!") } .multilineTextAlignment(.leading) } } }
1
3
264
Nov ’25
26.1b4 breaks zoom transition from tabViewBottomAccessory when fullScreenCover item is non-trivial Binding
Filed in Feedback as FB20772137 Zoom transition originating from inside tabViewBottomAccessory, when the binding passed to fullScreenCover's item is a Binding other than a "$-synthesized" binding, the animation fails with the following error (and crucially fails to perform the desired animation): Starting a zoom transition from a nil view will trigger a fallback transition. To get the best possible teansition, be sure to provide a view that's visible and in a window. What I want to do is pass a binding to a property inside an ObservableObject (or @Observable, but it doesn't matter) to hold the item representing the presentation. But this stopped working as of 26.1b4. It worked in 26.1b3 and in 26.0 (and 26.0.1) Here's the gist of code that will reproduce the issue (I've omitted irrelevant details in the interest of brevity): struct ContentView: View { @Binding var presentation: PresentationDestination? @Namespace private var animation var body: some View { // Omitted TabView stuff… .tabViewBottomAccessory { miniPlayer .matchedTransitionSource( id: "player", in: animation ) } .fullScreenCover( item: $presentation, content: { _ in fullScreenPlayer .navigationTransition( .zoom( sourceID: "player", in: animation ) ) }) } As you can see, ContentView takes a Binding to the presentation, but it matters how this binding is constructed. This works: @State private var presentation: PresentationDestination … ContentView(presentation: $presentation) This fails (as does ObservableObject with @Published): @Observable class Router2 { var presentation: PresentationDestination? } … @State private var router2 = Router2() … ContentView(presentation: $router2.presentation) Also, this fails: @State private var presentation: PresentationDestination … ContentView( presentation: .init(get: { presentation }, set: { newValue in presentation = newValue }) ) These differences are unexpected, of course. I consider this a regression in 26.1b4 I should add that if I move the source of the transition to somewhere outside tabViewBottomAccessory things seem to work fine.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
2
2
181
3h