fix swift 6 concurrency issues, clean build

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 23:01:21 +01:00
parent dca03214b0
commit 70aee19da0
6 changed files with 40 additions and 28 deletions

View File

@@ -291,6 +291,9 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = VoiceDiary/Info.plist;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -369,6 +372,9 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = VoiceDiary/Info.plist;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",

View File

@@ -2,6 +2,7 @@ import AVFoundation
import Foundation
@Observable
@MainActor
final class AudioRecorderService: NSObject {
var isRecording = false
var recordingDuration: TimeInterval = 0
@@ -35,8 +36,10 @@ final class AudioRecorderService: NSObject {
startTime = .now
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
guard let self, let startTime = self.startTime else { return }
self.recordingDuration = Date.now.timeIntervalSince(startTime)
Task { @MainActor in
guard let self, let startTime = self.startTime else { return }
self.recordingDuration = Date.now.timeIntervalSince(startTime)
}
}
return url
@@ -62,11 +65,13 @@ final class AudioRecorderService: NSObject {
}
extension AudioRecorderService: AVAudioRecorderDelegate {
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
if !flag {
isRecording = false
timer?.invalidate()
timer = nil
nonisolated func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
Task { @MainActor in
if !flag {
isRecording = false
timer?.invalidate()
timer = nil
}
}
}
}

View File

@@ -1,10 +1,11 @@
import Foundation
protocol SummarizationProvider {
protocol SummarizationProvider: Sendable {
func summarize(transcript: String, date: Date) async throws -> String
}
@Observable
@MainActor
final class SummarizationService {
var isSummarizing = false
@@ -14,15 +15,15 @@ final class SummarizationService {
self.provider = provider
}
func generateSummary(for entry: DiaryEntry) async throws -> String {
guard !entry.combinedTranscript.isEmpty else {
func generateSummary(transcript: String, date: Date) async throws -> String {
guard !transcript.isEmpty else {
throw SummarizationError.noTranscript
}
isSummarizing = true
defer { isSummarizing = false }
return try await provider.summarize(transcript: entry.combinedTranscript, date: entry.date)
return try await provider.summarize(transcript: transcript, date: date)
}
}

View File

@@ -2,6 +2,7 @@ import Foundation
import Speech
@Observable
@MainActor
final class TranscriptionService {
var authorizationStatus: SFSpeechRecognizerAuthorizationStatus = .notDetermined
@@ -25,8 +26,16 @@ final class TranscriptionService {
request.shouldReportPartialResults = false
request.addsPunctuation = true
let result = try await speechRecognizer.recognitionTask(with: request)
return result.bestTranscription.formattedString
let transcription: String = try await withCheckedThrowingContinuation { continuation in
speechRecognizer.recognitionTask(with: request) { result, error in
if let error {
continuation.resume(throwing: error)
} else if let result, result.isFinal {
continuation.resume(returning: result.bestTranscription.formattedString)
}
}
}
return transcription
}
}
@@ -43,17 +52,3 @@ enum TranscriptionError: LocalizedError {
}
}
}
private extension SFSpeechRecognizer {
func recognitionTask(with request: SFSpeechRecognitionRequest) async throws -> SFSpeechRecognitionResult {
try await withCheckedThrowingContinuation { continuation in
recognitionTask(with: request) { result, error in
if let error {
continuation.resume(throwing: error)
} else if let result, result.isFinal {
continuation.resume(returning: result)
}
}
}
}
}

View File

@@ -14,7 +14,9 @@ final class DiaryViewModel {
func generateSummary(for entry: DiaryEntry) async {
do {
let summary = try await summarizationService.generateSummary(for: entry)
let transcript = entry.combinedTranscript
let date = entry.date
let summary = try await summarizationService.generateSummary(transcript: transcript, date: date)
entry.summary = summary
entry.isSummaryGenerated = true
entry.updatedAt = .now

View File

@@ -31,6 +31,9 @@ targets:
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
ENABLE_PREVIEWS: true
SWIFT_EMIT_LOC_STRINGS: true
INFOPLIST_KEY_UILaunchScreen_Generation: true
INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad: "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"
entitlements:
path: VoiceDiary/VoiceDiary.entitlements
properties: