【发布时间】:2018-11-13 04:18:54
【问题描述】:
我在 Swift 中编写了一个图像选择器 (NOT UIImagePickerController),按“完成”后,我返回所选 PHAsset(图像或视频或两者)的 URL,然后将它们上传到firebase 存储。
图像的 URL 如下所示:file:///var/mobile/Media/DCIM/101APPLE/IMG_1239.PNG
视频的网址如下所示:file:///var/mobile/Media/DCIM/101APPLE/IMG_1227.MOV
然后我显示 PHAsset。播放视频资产没有问题:
let player = AVPlayer(url: url)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = view.frame
playerLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(playerLayer)
player.play()
但当我尝试使用其 URL 显示图像时,我收到“无权读取文件”错误:
do {
let data = try Data(contentsOf: url)
imageView.image = UIImage(data: data)
} catch {
print(error)
}
我确实有权访问用户的照片库,这就是图像选择器工作正常的原因。我只是无法使用它们的 URL 读取图像文件。
我在想,也许我应该将图像资源复制到一个临时文件并从那里读取它,但是为什么视频资源是可读的而不是图像资源是没有任何意义的。
-------------更新--------------
这就是我获取 PHAsset 网址的方式
extension PHAsset {
func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)) {
if self.mediaType == .image {
let options = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = { (adjustmeta: PHAdjustmentData) -> Bool in
return true
}
self.requestContentEditingInput(with: options, completionHandler: { (contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) in
completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
})
} else if self.mediaType == .video {
let options = PHVideoRequestOptions()
options.version = .original
PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) in
if let urlAsset = asset as? AVURLAsset {
let localVideoUrl: URL = urlAsset.url as URL
completionHandler(localVideoUrl)
} else {
completionHandler(nil)
}
})
}
}
}
【问题讨论】:
-
它与图像与视频无关。您将无法使用其 URL 直接访问视频数据,就像您无法从其 URL 访问图像数据一样。
-
@rmaddy,有道理。你认为我的图像选择器应该将选定的资产复制到一个临时文件然后从那里读取吗?我有其他选项,例如返回所选资产的数据,但是当我尝试这样做时会导致内存泄漏
-
您无权使用其 URL 复制资产。您需要使用 AVFoundation 的 API 来访问资产的数据。
-
@K.Wu 在显示图像时,您有
asset参考还是只有url? -
@staticVoidMan,仅 URL。实际上,我愿意更改图像选择器返回的数据。起初我的图像选择器通过调用
imageManager.requestImageData...返回资产的数据,但是对于像 GIF 图像这样的大图像,内存使用量很大,每次选择 GIF 时它会多消耗 20+MB 的内存。上传后,内存使用量一直保持不变,因此,如果用户一次上传 1 个 GIF 并重复执行此操作,应用程序将因内存泄漏而崩溃。这就是我的图像选择器返回 URL 的原因。你觉得我应该这样做吗?