Swi*_*bit 7 ios icloud avasset swift ios14
最近,开始注意到从照片库导入某些资产时没有显示它们。有问题的资产存储在 iCloud 中,不会缓存在设备上。我相信这是一个 iOS 14 问题,因为我从未在 iOS 13 上遇到过这个问题。(我不是 100% 确定,因为我无法将我的个人设备推出到 iOS 13)。
这是我在iOS 14 中所做的:
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
configuration.filter = PHPickerFilter.videos
let videoPickerController = PHPickerViewController(configuration: configuration)
videoPickerController.delegate = self
present(videoPickerController, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: nil)
guard results.count > 0 else {
return
}
guard let firstPHAssetIdentifier = results.first?.assetIdentifier else {
fatalError("No asset identifier")
}
let fetchOptions = PHFetchOptions()
guard let phAsset = PHAsset.fetchAssets(withLocalIdentifiers: [firstPHAssetIdentifier], options: fetchOptions).firstObject else {
fatalError("No matching PHAsset")
}
guard phAsset.mediaType == .video else {
fatalError("Asset not of the video type")
}
}
Run Code Online (Sandbox Code Playgroud)
let options = PHVideoRequestOptions()
options.isNetworkAccessAllowed = true
options.progressHandler = { progress, _, _, _ in
print("Progress: \(progress)")
}
PHCachingImageManager.default().requestAVAsset(forVideo: phAsset, options: options) { [weak self] avAsset, _, info in
guard info?[PHImageCancelledKey] == nil && info?[PHImageErrorKey] == nil else {
print("Error or cancelled. Info: \(String(describing: info))")
return
}
guard let avAsset = avAsset else {
print("Asset is nil. Info: \(String(describing: info))")
return
}
guard let videoTrack = avAsset.tracks(withMediaType: .video).first else {
print("Cound not extract video track from AvAsset") // <- My issue
return
}
}
Run Code Online (Sandbox Code Playgroud)
问题:通常,当资产来自 iCloud 时,我不会有 videoTrack。avAsset.duration 也将为0.0。
我会看到下载进度,但我会陷入最后的守卫声明。有时,一旦资产已下载并且无法加载 videoTrack,重试将立即失败(它不会再次尝试加载资产,似乎它已损坏)。它将落入最后的守卫声明。
我注意到在 PHVideoRequestOptions 上使用 deliveryMode = .highQualityFormat 使其工作,但我宁愿只下载 720p 视频,而不是高质量视频。
我想我在这里做错了什么。我应该以这种方式从 PHPickerResult 获取 phAsset 吗?任何指针/帮助将不胜感激。我创建了这个 repo 来复制https://github.com/SwiftRabbit/RequestAVAssetIssues/tree/main/RequestAVAssetIssues。不能 100% 重现,并且必须是不再存在于设备上的 iCloud 视频。
附加说明/尝试:
我能够通过在 iPad 上录制视频、等待视频同步到 iCloud,然后在 iPhone SE 2016 上请求 AVAsset 来重现该问题。我在 github 上创建了一个存储库来说明这一点。这是一个 Objective-C 项目,但是对于 Swift 来说结论应该是一样的。存储库的重要部分位于https://github.com/Jan-E/ikyle.me-code-examples/blob/master/Photo%20Picker%20ObjC/Photo%20Picker%20ObjC/PHPickerController.m
这是我正在使用的代码:
for (PHAsset *phAsset in assetResults) {
float recordingDuration = phAsset.duration;
NSLog(@"recordingDuration %f", recordingDuration);
NSDate *PHAssetCreationDate = phAsset.creationDate;
NSLog(@"PHAssetCreationDate %@", PHAssetCreationDate);
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
options.networkAccessAllowed = NO;
[[PHImageManager defaultManager] requestAVAssetForVideo:phAsset
options:options
resultHandler:^(AVAsset *avAsset, AVAudioMix *audioMix, NSDictionary *info) {
NSURL *videoURL = (NSURL *)[[(AVURLAsset *)avAsset URL] fileReferenceURL];
NSLog(@"videoURL absoluteString = %@", [videoURL absoluteString]);
NSLog(@"videoURL relativePath = %@", [videoURL relativePath]);
AVURLAsset *avUrl = [AVURLAsset assetWithURL:videoURL];
CMTime time = [avUrl duration];
float recordingDuration;
recordingDuration = time.value/time.timescale;
NSArray *tracks = [avUrl tracksWithMediaType:AVMediaTypeVideo];
NSLog(@"duration %f, tracks %lu", recordingDuration, (unsigned long)tracks.count);
}];
}
Run Code Online (Sandbox Code Playgroud)
当视频仍然仅在 iCloud 上时,这些是 NSLog 返回的结果:
通过使用,result.itemProvider loadFileRepresentationForTypeIdentifier您可以强制将视频从 iCloud 下载到设备。那么结果如下:
完整的 NSLog 输出位于完成该操作的 2 个提交中的最后一个下面的 2 个注释中:https://github.com/Jan-E/ikyle.me-code-examples/commit/2d0174c2766abf742b6d76d053abc0a46199358f
编辑:请注意,在设备上没有视频的情况下启动的示例中,从 iCloud 下载 1.2GB 视频需要 4:23 分钟 (2020-12-24 15:45:13.669505+0100 - 2020-12-24 15: 49:36.224240+0100)。并非在所有情况下都需要下载。phAsset.duration 的值为 680.044983 秒的信息可能是您在应用程序中需要的所有信息,因为它意味着视频至少有 1 个轨道。
编辑2:通过使用options:nil我正在使用隐式networkAccessAllowed = NO. 通过编辑,我将其明确化。它还可能给出持续时间 0.0 和跟踪 0 的解释。如果允许网络访问,但网络连接失败怎么办?然后,您仍然会获得有意义的 phAsset.duration 值(来自早期的 iCloud 同步),但不会获得 avAsset 的实时值。
| 归档时间: |
|
| 查看次数: |
1088 次 |
| 最近记录: |