Had to repost this question because no one answered, it's been 2 weeks, and I am absolutely clueless on why this is happening. I am using the following function to convert a PHAsset to a url:
extension PHAsset {
func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)){
if self.mediaType == .image {
let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
return true
}
options.isNetworkAccessAllowed = true
self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
})
} else if self.mediaType == .video {
let options: PHVideoRequestOptions = PHVideoRequestOptions()
options.version = .original
options.isNetworkAccessAllowed = true
PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
if let urlAsset = asset as? AVURLAsset {
let localVideoUrl: URL = urlAsset.url as URL
completionHandler(localVideoUrl)
} else {
completionHandler(nil)
}
})
}
}
}
However the url ends up coming out nil sometimes causing my app to crash. I have noticed it is more common if I choose a video on the longer side rather than a picture but I can not pin point exactly when it happens. Also, this does not seem like an issue just I am having because on the stack overflow post I got this from, the recent comment asks why the asset is sometimes nil. The post: How to get URL for a PHAsset? [duplicate]
Edit
I changed code to this:
func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)){
if self.mediaType == .image {
let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
// options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
// return true
// }
// options.isNetworkAccessAllowed = true
self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
if let contentEditingInput = contentEditingInput {
completionHandler(contentEditingInput.fullSizeImageURL)
} else {
completionHandler(nil)
}
})
} else if self.mediaType == .video {
let options: PHVideoRequestOptions = PHVideoRequestOptions()
// options.version = .original
// options.isNetworkAccessAllowed = true
PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
if let urlAsset = asset as? AVURLAsset {
let localVideoUrl: URL = urlAsset.url as URL
completionHandler(localVideoUrl)
} else {
completionHandler(nil)
}
})
}
}
But still no luck. My app is not crashing its just every now and then the urls come out to be nil.
self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
})
contentEditingInput is marked as optional, why would anyone implicitly unwrap it is beyond me. To safely unwrap it (which will prevent your app from crashing), do something like this:
if let contentEditingInput = contentEditingInput {
completionHandler(contentEditingInput.fullSizeImageURL)
} else {
completionHandler(nil)
}
You do not need as URL? because, documentation:
var fullSizeImageURL: URL? { get }
Trying commenting out the line where you set the image options. I have an app that uses this API working fine, but I do not have those options set. This option could be the cause why contentEditingInput is nil.
Edit - getting URL of image or movie from Photo Library using UIImagePickerController
import MobileCoreServices
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let mediaType = info[UIImagePickerController.InfoKey.mediaType] as? String,
mediaType == (kUTTypeMovie as String) else { return }
let videoURL = info[.mediaURL] as? URL
}
Above is the way I used to get videoURL, below is for image.
guard let mediaType = info[UIImagePickerController.InfoKey.mediaType] as? String,
mediaType == (kUTTypeImage as String) else { return }
let photoURL = info[.imageURL] as? URL