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

Swift中如何在类与视图间保持AudioRecorder对象状态不丢失?

解决SwiftUI中跨视图保持AudioRecorder状态的问题

你的核心问题是跳转至RatingView时新建了全新的AudioRecorder实例,而非传递之前已经完成录制的那个实例,导致原有startTime、stopTime的状态完全丢失。以下是具体的修复方案:

1. 传递已有AudioRecorder实例而非新建

在RecorderView的NavigationLink中,把你当前持有的audioRecorder实例传递给RatingView,而不是创建新的:

// 替换RecorderView中的NavigationLink代码
if showRatingView == true {
    NavigationLink(
        destination: RatingView(rating: 1, audioRecorder: audioRecorder),
        isActive: self.$showRatingView
    ) { EmptyView() }
}

2. 修正AudioRecorder的状态定义与方法

当前AudioRecorder的startTime和stopTime是非可选的Date类型,但未初始化,这会导致编译错误,同时不符合“录制前无时间值”的业务逻辑。另外saveToCoreData方法中直接使用未定义的moc也是问题,需要修正:

class AudioRecorder: NSObject, ObservableObject {
    @Published var startTime: Date? // 改为可选类型,录制前为nil
    @Published var stopTime: Date?
    @Published var recording = false // 补充你原代码中用到的recording状态

    func startRecording() {
        self.startTime = Date()
        self.recording = true
        // 此处添加实际录制逻辑
    }

    func stopRecording() {
        self.stopTime = Date()
        self.recording = false
        // 此处添加停止录制逻辑
    }

    func saveToCoreData(rating: Int16, moc: NSManagedObjectContext) {
        // 先校验录制时间是否存在,避免空值崩溃
        guard let startTime = startTime, let stopTime = stopTime else {
            print("错误:未完成录制,无法保存数据")
            return
        }
        
        let aRec = AudioRec(context: moc)
        aRec.uuid = UUID()
        aRec.startTime = startTime
        aRec.stopTime = stopTime
        aRec.rating = rating

        do {
            try moc.save()
        } catch {
            print("保存数据失败:\(error.localizedDescription)")
        }
    }
}

3. 在RatingView中正确调用保存方法

修改RatingView的按钮动作,将环境中的Core Data上下文传递给saveToCoreData方法:

struct RatingView: View {
    @Environment(\.managedObjectContext) var moc
    @State var rating: Int16
    @ObservedObject var audioRecorder: AudioRecorder

    @State private var displayNewView: Bool = false

    var body: some View {
        VStack {
            Text("How was the recording experience?")
            // 这里可以添加你的评分选择控件,比如将@State rating改为绑定值实现交互
            Button(action: {
                audioRecorder.saveToCoreData(rating: rating, moc: moc)
                // 保存完成后可根据需求跳转或返回
                displayNewView = true
            }) {
                Text("Submit Response")
            }
        }
        .navigationBarBackButtonHidden(true)
    }
}

关键注意点

  • 始终在视图间传递同一个ObservableObject实例,保证状态的连续性
  • 用可选类型合理表示“未初始化”的状态,避免不必要的默认值
  • 不要在业务类(如AudioRecorder)中直接持有Core Data上下文,通过视图的环境变量传递更符合SwiftUI的设计逻辑
  • 添加必要的校验与错误处理,避免因异常状态导致崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 20:35:17