如何消除AVAssetExportSession导出时的主线程隔离数据竞争警告?
消除AVAssetExportSession导出时的Sendable警告
你遇到的警告是因为AVAssetExportSession并非Sendable类型,在非主actor隔离的上下文里传递这类对象可能引发数据竞争——AVFoundation的多数API设计为在主队列/主actor环境下使用。以下是两种可行的解决方式:
方式一:仅将导出相关操作限定在主actor执行
把涉及exportSession的设置、导出调用及状态检查逻辑,用MainActor.run包裹,确保这部分代码在主actor上下文运行:
func extractAudioFromImportedVideo(videoURL: URL, success: @escaping ((URL) -> Void), failure: @escaping ((Error?) -> Void)) async { do { let asset = AVURLAsset(url: videoURL) let audioTracks = try await asset.loadTracks(withMediaType: .audio) guard !audioTracks.isEmpty else { failure(NSError(domain: "Audio Extraction Error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Video does not contain audio"])) return } guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else { failure(NSError(domain: "Audio Extraction Error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to create export session"])) return } guard let audioURL = makeFileOutputURL(fileName: "ExtractedAudio.m4a") else { failure(NSError(domain: "Audio Extraction Error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to create output URL"])) return } print("audioTracks", audioTracks) // 用MainActor.run包裹导出相关逻辑 await MainActor.run { exportSession.outputURL = audioURL exportSession.outputFileType = .m4a await exportSession.export() print("exportSession.status", exportSession.status.rawValue) if exportSession.status == .completed { print("Audio extraction succeeded") success(audioURL) } else { print("Audio extraction failed: \(exportSession.error?.localizedDescription ?? "")") failure(exportSession.error) } } } catch { print("extractAudioFromImportedVideo Error:", error.localizedDescription) } }
这种方式的优势是仅将必要的UI/AVFoundation相关操作放在主actor,避免阻塞主队列处理其他耗时任务(比如asset.loadTracks这类异步加载操作仍可在后台执行)。
方式二:将整个函数标记为主actor隔离
如果函数内所有操作都适合在主actor执行(比如没有大量后台耗时任务),可以直接给函数添加@MainActor标记:
@MainActor func extractAudioFromImportedVideo(videoURL: URL, success: @escaping ((URL) -> Void), failure: @escaping ((Error?) -> Void)) async { // 原代码内容保持不变 }
这样整个函数的所有逻辑都会在主actor上下文运行,自然消除跨actor传递非Sendable对象的警告。
内容的提问来源于stack exchange,提问作者Hassan Taleb
相关产品推荐
相关产品推荐

