harden stopRecording with defensive error handling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 23:21:05 +01:00
parent 8c4e085890
commit edb4b8a567
2 changed files with 24 additions and 25 deletions

View File

@@ -6,12 +6,10 @@ import SwiftData
@MainActor
final class RecordingViewModel {
var isRecording = false
var recordingDuration: TimeInterval = 0
var error: Error?
private let recorder = AudioRecorderService()
private let transcriptionService = TranscriptionService()
private var currentRecordingURL: URL?
var formattedDuration: String {
let minutes = Int(recorder.recordingDuration) / 60
@@ -21,7 +19,7 @@ final class RecordingViewModel {
func startRecording() {
do {
currentRecordingURL = try recorder.startRecording()
_ = try recorder.startRecording()
isRecording = true
error = nil
} catch {
@@ -30,23 +28,26 @@ final class RecordingViewModel {
}
func stopRecording(context: ModelContext) {
guard let result = recorder.stopRecording() else { return }
guard let result = recorder.stopRecording() else {
isRecording = false
return
}
isRecording = false
let today = Calendar.current.startOfDay(for: .now)
let entry = fetchOrCreateEntry(for: today, context: context)
let fileName = result.url.lastPathComponent
let duration = result.duration
let memo = VoiceMemo(
audioFileName: result.url.lastPathComponent,
duration: result.duration
)
context.insert(memo)
let entry: DiaryEntry
do {
entry = try fetchOrCreateEntry(for: .now, context: context)
} catch {
self.error = error
return
}
let memo = VoiceMemo(audioFileName: fileName, duration: duration)
memo.entry = entry
if entry.memos == nil { entry.memos = [] }
entry.memos?.append(memo)
entry.updatedAt = .now
try? context.save()
context.insert(memo)
let audioURL = memo.audioURL
Task {
@@ -54,17 +55,16 @@ final class RecordingViewModel {
}
}
private func fetchOrCreateEntry(for date: Date, context: ModelContext) -> DiaryEntry {
private func fetchOrCreateEntry(for date: Date, context: ModelContext) throws -> DiaryEntry {
let startOfDay = Calendar.current.startOfDay(for: date)
let descriptor = FetchDescriptor<DiaryEntry>()
let entries = try context.fetch(descriptor)
if let entries = try? context.fetch(descriptor) {
let match = entries.first { entry in
Calendar.current.isDate(entry.date, inSameDayAs: date)
}
if let match { return match }
if let match = entries.first(where: { Calendar.current.isDate($0.date, inSameDayAs: startOfDay) }) {
return match
}
let entry = DiaryEntry(date: date)
let entry = DiaryEntry(date: startOfDay)
context.insert(entry)
return entry
}
@@ -84,7 +84,6 @@ final class RecordingViewModel {
let transcript = try await transcriptionService.transcribe(audioURL: audioURL)
memo.transcript = transcript
memo.isTranscribing = false
memo.entry?.updatedAt = .now
} catch {
memo.isTranscribing = false
self.error = error

View File

@@ -3,7 +3,7 @@ import SwiftUI
struct RecordingView: View {
@Environment(\.modelContext) private var modelContext
@Environment(\.dismiss) private var dismiss
@Bindable var viewModel: RecordingViewModel
var viewModel: RecordingViewModel
var body: some View {
NavigationStack {