I have a SwiftUI
Form
with a custom chart view (not Swift Charts). A long press toggles to a different type of chart. These charts use the .transition(.slide)
modifier. In iOS 15 these transitioned as expected on a long press, but in iOS 16 they do not.
Persisted state property (an enum):
@AppStorage("chartType") var chartType: ChartType = .chartA
The Form
part of the body
property:
Form {
// Other sections
Section {
switch chartType {
case .chartA:
ChartViewA()
.transition(.slide)
case .chartB:
ChartViewB()
.transition(.slide)
}
.onLongPressGesture {
if chartType == .chartA {
withAnimation {
summaryChartType = .chartB
}
} else {
withAnimation {
summaryChartType = .chartA
}
}
}
Unfortunately adding animation modifiers like .animation(.spring(), value: chartType)
makes no difference.
I would be grateful for advice on why this might have worked in iOS 15 but not in iOS 16, and what I could do to restore animation here.
In iOS 16, there appears to be a problem with @AppStorage
vars and animation. Here is one possible workaround. Use @State
var for animation, and save it to an @AppStorage
variable with .onChange()
:
enum ChartType: String {
case chartA, chartB
}
struct ChartViewA: View {
var body: some View {
Color.red
}
}
struct ChartViewB: View {
var body: some View {
Color.blue
}
}
struct ContentView: View {
@AppStorage("chartType") var chartTypeAS: ChartType = .chartA
@State private var chartType: ChartType = .chartA
init() {
// load initial value from persistent storage
_chartType = State(initialValue: chartTypeAS)
}
var body: some View {
Form {
// Other sections
Section {
VStack {
switch chartType {
case .chartA:
ChartViewA()
.transition(.slide)
case .chartB:
ChartViewB()
.transition(.slide)
}
}
.onLongPressGesture {
if chartType == .chartA {
withAnimation {
chartType = .chartB
}
} else {
withAnimation {
chartType = .chartA
}
}
}
}
.onChange(of: chartType) { value in
// persist chart type
chartTypeAS = value
}
}
}
}
Tested in Xcode 14.0 with iPhone 14 simulator running iOS 16.
Alternatively, you could perform the saving to/restoring from UserDefaults
manually.