Swift中AVAsset.duration已废弃,同步函数中如何改用异步替代?
解决AVAsset异步加载属性后依赖代码的执行问题
由于AVAsset的同步属性(如duration、tracks)已被废弃,改用异步load(_:)方法后,核心问题是确保依赖这些属性的代码在加载完成后执行,以下是几种可行的处理方式:
1. 将依赖逻辑直接移入异步任务内部
把原本需要用到duration、fps的后续代码(比如文件完整性检查),直接放在异步加载成功的代码块中,这样能保证数据准备好后再执行逻辑:
Task { do { // 异步加载所需属性 self.duration = try await avAsset.load(.duration) self.tracks = try await avAsset.load(.tracks) self.fps = try await self.tracks.first?.load(.nominalFrameRate) ?? 30 // 这里执行依赖这些属性的后续逻辑,比如文件完整性检查 checkFileIntegrity() } catch { Globals.logger.error("MoviePlayer - loadMovie error fetching metadata") // 可选:添加错误后的降级处理,比如标记文件无效 } } // 定义文件完整性检查函数 private func checkFileIntegrity() { // 用已加载的属性执行检查逻辑 if self.duration.seconds <= 0 || self.fps <= 0 { // 处理文件不完整的情况 } }
2. 将加载逻辑封装为异步函数,调用时等待完成
如果原同步函数可以改为异步函数,可将属性加载逻辑封装成单独的async throws方法,调用时通过await等待加载完成,再执行后续代码:
// 封装异步加载逻辑 private func loadMovieMetadata() async throws { self.duration = try await avAsset.load(.duration) self.tracks = try await avAsset.load(.tracks) self.fps = try await self.tracks.first?.load(.nominalFrameRate) ?? 30 } // 调用时(非异步上下文用Task包裹) Task { do { try await loadMovieMetadata() // 加载完成后执行依赖逻辑 checkFileIntegrity() } catch { Globals.logger.error("MoviePlayer - loadMovie error fetching metadata") } }
3. 确保主线程更新UI/属性
如果duration、fps等属性用于更新UI,需注意异步任务默认可能不在主线程执行,要通过MainActor确保UI更新在主线程:
方式一:直接在Task中指定MainActor
Task { @MainActor in do { self.duration = try await avAsset.load(.duration) self.tracks = try await avAsset.load(.tracks) self.fps = try await self.tracks.first?.load(.nominalFrameRate) ?? 30 checkFileIntegrity() // 这里可以直接更新UI,比如刷新播放进度显示 } catch { Globals.logger.error("MoviePlayer - loadMovie error fetching metadata") } }
方式二:先加载数据,再在主线程更新属性
Task { do { // 先在后台加载数据 let duration = try await avAsset.load(.duration) let tracks = try await avAsset.load(.tracks) let fps = try await tracks.first?.load(.nominalFrameRate) ?? 30 // 切换到主线程更新属性和执行逻辑 await MainActor.run { self.duration = duration self.tracks = tracks self.fps = fps checkFileIntegrity() } } catch { Globals.logger.error("MoviePlayer - loadMovie error fetching metadata") } }
内容的提问来源于stack exchange,提问作者Pete
相关产品推荐
相关产品推荐

