After iOS 17 updated, if I enter a value or change Value in a text field and then go to the multitasking window or put the app in background mode and come back, the value is reset to its initial state. When the app goes into background mode or a multitasking window, does it call onAppear again to return the view to its initial state?
Is there any way to preserve input values in iOS17? This code was working fine on IOS 16.
struct RealSizeView: View {
private enum Field: Hashable {
case shoulder, chest, sleeve, length, waist, thigh, rise, hem, inseam
}
let realSizeType: RealSizeType
@Binding var originalShoulder: Double
@Binding var originalChest: Double
@Binding var originalSleeve: Double
@Binding var originalLength: Double
@Binding var originalWaist: Double
@Binding var originalThigh: Double
@Binding var originalRise: Double
@Binding var originalHem: Double
@Binding var originalInseam: Double
@State private var editedShoulder: Double = 0
@State private var editedChest: Double = 0
@State private var editedSleeve: Double = 0
@State private var editedLength: Double = 0
@State private var editedWaist: Double = 0
@State private var editedThigh: Double = 0
@State private var editedRise: Double = 0
@State private var editedHem: Double = 0
@State private var editedInseam: Double = 0
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationStack {
ZStack(alignment: .bottom) {
Form {
Section {
switch realSizeType {
case .top:
topView
case .bottom:
bottomView
}
}
}
}
.navigationTitle("Size")
.onAppear {
initValue()
}
private func initValue() {
switch realSizeType {
case .top:
editedShoulder = originalShoulder
editedChest = originalChest
editedSleeve = originalSleeve
editedLength = originalLength
case .bottom:
editedWaist = originalWaist
editedThigh = originalThigh
editedRise = originalRise
editedHem = originalHem
editedInseam = originalInseam
}
}
@ViewBuilder
var topView: some View {
RealSizeInputRowView(title: Top.shoulder.name, amount: $editedShoulder, unit: unit)
.focused($focusedField, equals: .shoulder)
.onTapGesture { focusedField = .shoulder }
RealSizeInputRowView(title: Top.chest.name, amount: $editedChest, unit: unit)
.focused($focusedField, equals: .chest)
.onTapGesture { focusedField = .chest }
RealSizeInputRowView(title: Top.sleeve.name, amount: $editedSleeve, unit: unit)
.focused($focusedField, equals: .sleeve)
.onTapGesture { focusedField = .sleeve }
RealSizeInputRowView(title: Top.length.name, amount: $editedLength, unit: unit)
.focused($focusedField, equals: .length)
.onTapGesture { focusedField = .length }
}
@ViewBuilder
var bottomView: some View {
RealSizeInputRowView(title: Bottom.waist.name, amount: $editedWaist, unit: unit)
.focused($focusedField, equals: .waist)
.onTapGesture { focusedField = .waist }
RealSizeInputRowView(title: Bottom.thigh.name, amount: $editedThigh, unit: unit)
.focused($focusedField, equals: .thigh)
.onTapGesture { focusedField = .thigh }
RealSizeInputRowView(title: Bottom.rise.name, amount: $editedRise, unit: unit)
.focused($focusedField, equals: .rise)
.onTapGesture { focusedField = .rise }
RealSizeInputRowView(title: Bottom.hem.name, amount: $editedHem, unit: unit)
.focused($focusedField, equals: .hem)
.onTapGesture { focusedField = .hem }
RealSizeInputRowView(title: Bottom.inseam.name, amount: $editedInseam, unit: unit)
.focused($focusedField, equals: .inseam)
.onTapGesture { focusedField = .inseam }
}
Maybe you could use scenePhase to preserve the values? ScenePhase documentation. I remember it from Hacking With Swift that kept the timer running while the app went into the background.