You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS17中App后台/多任务返回输入值重置问题咨询

问题解答

1. 后台/多任务返回时是否会触发onAppear导致重置?

是的,iOS17调整了SwiftUI的视图生命周期逻辑,当App从后台回到前台、或进入多任务切换后返回时,视图的onAppear会被重新触发。你的代码中在onAppear里调用了initValue(),这个方法会把edited*系列变量重新赋值为original*的初始值,这就是输入内容被重置的原因。而iOS16中onAppear不会在这类场景下重复触发,所以之前运行正常。

2. iOS17中保留输入值的解决方法

核心思路是让编辑值的初始化只执行一次,避免在onAppear这种会重复触发的回调里重置数据,具体有两种可行方案:

方案一:通过视图初始化器初始化编辑值

把initValue()的逻辑移到视图的自定义初始化器中,这样初始化只会在视图创建时执行一次,不会在后台返回时重复执行:

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
    
    // 添加自定义初始化器
    init(realSizeType: RealSizeType,
         originalShoulder: Binding<Double>,
         originalChest: Binding<Double>,
         originalSleeve: Binding<Double>,
         originalLength: Binding<Double>,
         originalWaist: Binding<Double>,
         originalThigh: Binding<Double>,
         originalRise: Binding<Double>,
         originalHem: Binding<Double>,
         originalInseam: Binding<Double>) {
        self.realSizeType = realSizeType
        self._originalShoulder = originalShoulder
        self._originalChest = originalChest
        self._originalSleeve = originalSleeve
        self._originalLength = originalLength
        self._originalWaist = originalWaist
        self._originalThigh = originalThigh
        self._originalRise = originalRise
        self._originalHem = originalHem
        self._originalInseam = originalInseam
        
        // 初始化编辑值,仅执行一次
        switch realSizeType {
        case .top:
            self._editedShoulder = State(initialValue: originalShoulder.wrappedValue)
            self._editedChest = State(initialValue: originalChest.wrappedValue)
            self._editedSleeve = State(initialValue: originalSleeve.wrappedValue)
            self._editedLength = State(initialValue: originalLength.wrappedValue)
        case .bottom:
            self._editedWaist = State(initialValue: originalWaist.wrappedValue)
            self._editedThigh = State(initialValue: originalThigh.wrappedValue)
            self._editedRise = State(initialValue: originalRise.wrappedValue)
            self._editedHem = State(initialValue: originalHem.wrappedValue)
            self._editedInseam = State(initialValue: originalInseam.wrappedValue)
        }
    }
    
    var body: some View {
        NavigationStack {
            ZStack(alignment: .bottom) {
                Form {
                    Section {
                        switch realSizeType {
                        case .top:
                            topView
                        case .bottom:
                            bottomView
                        }
                    }
                }
            }
            .navigationTitle("Size")
            // 移除原来的onAppear回调
        }
    }
    
    private func initValue() {
        // 这个方法可以删除了
    }
    
    // 以下topView、bottomView代码保持不变
    @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 }
    }
}

方案二:使用@AppStorage持久化编辑值(可选)

如果需要在App重启后也保留输入值,可以用@AppStorage替代@State存储编辑值,这样数据会自动保存到本地:

// 示例:把@State替换为@AppStorage,给每个值指定唯一的存储键
@AppStorage("editedShoulder") private var editedShoulder: Double = 0
@AppStorage("editedChest") private var editedChest: Double = 0
// 其他edited*变量同理替换

这种情况下,即使App重启或后台返回,编辑值也会保留。但注意如果多个页面使用相同的存储键会导致数据冲突,需要确保键的唯一性。

内容的提问来源于stack exchange,提问作者idhun90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 09:17:34