如何在SwiftUI View中加载AVAsset元数据且无编译器警告?
解决AVAsset.load(.metadata)的Sendable警告问题
修正后的完整代码
currentMediaTitle = "" Task { guard let asset = player.currentItem?.asset else { await MainActor.run { currentMediaTitle = nil } return } // 消除第一个警告:显式标记数组为@unchecked Sendable let allMetadata = try await asset.load(.metadata) as! [AVMetadataItem] & @unchecked Sendable guard let titleMetadata = allMetadata.first(where: { item in item.identifier == AVMetadataIdentifier.commonIdentifierTitle }) else { await MainActor.run { currentMediaTitle = nil } return } // 消除第二个警告:在MainActor上下文调用load方法 let titleValue = try await MainActor.run { try await titleMetadata.load(.value) } let title = (titleValue as? NSString) as String? await MainActor.run { self.currentMediaTitle = title } }
具体警告的解决逻辑
针对
[AVMetadataItem]跨actor边界的警告
AVFoundation的AVMetadataItem尚未被官方标记为Sendable协议兼容,但AVFoundation绝大多数API本身是线程安全的。我们可以通过as! [AVMetadataItem] & @unchecked Sendable显式告诉编译器:我们确认这个类型可以安全跨actor传递,无需担心数据竞争。针对
AVMetadataItem跨上下文传递的警告
调用titleMetadata.load(.value)时,编译器认为非Sendable的AVMetadataItem实例被跨线程传递。通过将该调用包裹在MainActor.run中,强制在主线程上下文执行方法,消除编译器的风险顾虑。关于MainActor的正确使用
你之前尝试放在MainActor中仍有警告,大概率是因为没有明确将Task的执行上下文绑定到MainActor。使用MainActor.run包裹UI更新和敏感API调用,能确保所有相关操作都在主线程执行。
警告根源说明
- 旧的
.metadata属性被弃用后,新的load方法采用结构化并发,但AVFoundation的部分类(如AVAsset、AVMetadataItem)还没跟上Swift并发模型的Sendable标记要求。 - 编译器将这些类视为非Sendable,因此会对跨actor传递或跨上下文调用发出警告,即便这些类在实际使用中是线程安全的。
内容的提问来源于stack exchange,提问作者Ky -
相关产品推荐
相关产品推荐

