Goo*_*rel 5 asynchronous avfoundation ios avasset
我试图asset从AVAssetTrack对象中获取属性,但nil有时会这样。看来这个问题是我使用后才出现的Dispatch.main.async。
根据文档,有必要使用loadValuesAsynchronously(forKeys:, completion:)以避免阻塞主线程,并在加载完成后返回主线程。
let asset = AVURLAsset(url: videoInAppBundleURL)
let track = asset.tracks(withMediaType: .video).first!
assert(track.asset != nil) // passes
track.loadValuesAsynchronously(forKeys: [#keyPath(AVAssetTrack.asset)]) {
assert(track.asset != nil) // passes
DispatchQueue.main.async {
assert(track.asset != nil) // FAILS
// [...]
}
}
Run Code Online (Sandbox Code Playgroud)
我发现的是:
这是一个工作演示项目。
我还想知道:为什么AVAssetTrack的asset属性是可选的?(所有!!其他属性都是非可选的)
注意:在阅读马特的有用评论和进一步调查后,这个问题已被编辑。
我重现了这个问题,并对你的 github 示例进行了一些调整,如下所示:
\n\n let asset = AVURLAsset(url: videoInAppBundleURL)\n let tracksKey = #keyPath(AVAsset.tracks)\n asset.loadValuesAsynchronously(forKeys: [tracksKey]) {\n let track = asset.tracks(withMediaType: .video).first!\n DispatchQueue.main.async {\n assert(track.asset != nil) // fails\n }\n }\nRun Code Online (Sandbox Code Playgroud)\n\n好的,但现在请仔细观看我表演一个惊人的技巧:
\n\n let asset = AVURLAsset(url: videoInAppBundleURL)\n let tracksKey = #keyPath(AVAsset.tracks)\n asset.loadValuesAsynchronously(forKeys: [tracksKey]) {\n let track = asset.tracks(withMediaType: .video).first!\n DispatchQueue.main.async {\n print(asset) // <-- amazing trick\n assert(track.asset != nil) // passes!\n }\n }\nRun Code Online (Sandbox Code Playgroud)\n\n哇!我所做的只是添加一条print语句 \xe2\x80\x94 ,现在突然相同的断言通过了。事实上,这与您最初的声明(您后来将其删除)平行:“有时,当使用调试器单步执行代码时,问题就消失了。\xe2\x80\x9d
所以,现在,我的怀疑被彻底激起,我做了一件令人难以置信的聪明事(即使我自己这么说)。我删除了print(asset),但我将 schema\xe2\x80\x99s 配置从 Debug 切换到 Release。转眼间,这个断言仍然成立。
那么你\xe2\x80\x99ve发现的是编译器\xe2\x80\x94的一个怪癖,我敢称之为错误吗?
\n\n但是等等,还有\xe2\x80\x99s。你问的很合理,为什么asset是可选的。它\xe2\x80\x99s 因为它\xe2\x80\x99s weak:
weak open var asset: AVAsset? { get }\nRun Code Online (Sandbox Code Playgroud)\n\n这就是你的答案。该曲目对其资产的引用很弱。如果我们将轨道传递到异步队列中,并且不将资产本身带入,那么弱引用就会消失,并且资产会在调试构建中丢失\xe2\x80\x94。
\n\n希望这可以帮助。您可能正在等待我就这是否构成错误做出一些宏大的结论性陈述,但抱歉,我\xe2\x80\x99m 不会这样做。我\xe2\x80\x99ve提供了两种解决方法(使用发布版本,或故意将资产引用放入异步队列中),并且\xe2\x80\x99s尽我所能。
\n