Reputation: 65
When I'm choosing image using image picker just after changing the permission settings for library in settings.
I'm getting an exception from OS. And the app is stuck. even didPickImageMedia delegate is not fired.
2018-05-07 11:08:04.413510+0530 PersonalCare[1369:75557] [general] <NSXPCConnection: 0x1c41153c0> connection from pid 1374: Warning:
Exception caught during invocation of received message, dropping incoming message and invalidating the connection. Exception: * -[NSURL URLByAppendingPathExtension:]: component, components, or pathExtension cannot be nil. * -[NSURL URLByAppendingPathExtension:]: component, components, or pathExtension cannot be nil. ( 0 CoreFoundation 0x000000018423bd50 + 148 1 libobjc.A.dylib 0x0000000183750528 objc_exception_throw + 56 2 CoreFoundation 0x000000018423bc80 + 0 3 Foundation 0x0000000184c4d91c + 92 4 PhotosUI 0x000000019707d4a0 + 1660 5 PhotosUI 0x000000019707c92c + 36 6 Foundation 0x0000000184d501e0 + 20 7 Foundation 0x0000000184d4e97c + 2632 8 Foundation 0x0000000184b25830 + 240 9 libxpc.dylib 0x0000000183ea2300 + 68 10 libxpc.dylib 0x0000000183e9fcb0 + 984 11 libdispatch.dylib 0x000000010371152c _dispatch_client_callout4 + 16 12 libdispatch.dylib 0x0000000103714f58 _dispatch_mach_msg_invoke + 380 13 libdispatch.dylib 0x000000010371ff30 _dispatch_queue_serial_drain + 212 14 libdispatch.dylib 0x00000001037144c0 _dispatch_mach_invoke + 992 15 libdispatch.dylib 0x000000010371ff30 _dispatch_queue_serial_drain + 212 16 libdispatch.dylib 0x00000001037149a4 _dispatch_queue_invoke + 332 17 libdispatch.dylib 0x0000000103721104 _dispatch_root_queue_drain_deferred_wlh + 424 18 libdispatch.dylib 0x0000000103728100 _dispatch_workloop_worker_thread + 652 19 libsystem_pthread.dylib 0x0000000183e66fe0 _pthread_wqthread + 932 20 libsystem_pthread.dylib 0x0000000183e66c30 start_wqthread + 4 )
My code
extension ProfileViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
buttonImage.contentMode = .scaleAspectFit
let imageData: Data = UIImageJPEGRepresentation(pickedImage, 0.7)!
encoded = imageData.base64EncodedString(options: .endLineWithCarriageReturn)
profileImage = pickedImage
buttonImage.setBackgroundImage(pickedImage, for: .normal)
} else if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
buttonImage.contentMode = .scaleAspectFit
let imageData: Data = UIImageJPEGRepresentation(pickedImage, 0.7)!
profileImage = pickedImage
encoded = imageData.base64EncodedString(options: .endLineWithCarriageReturn)
buttonImage.setBackgroundImage(pickedImage, for: .normal)
}
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
}
Upvotes: 3
Views: 2342
Reputation: 2719
Because many functions of UIImagePickerViewController will removed in future release(new version iOS14). You should using PHPickerViewController
import PhotosUI
if #available(iOS 14, *) {
// using PHPickerViewController
var config = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
config.selectionLimit = 1
config.filter = .images
config.preferredAssetRepresentationMode = .current
let picker = PHPickerViewController(configuration: config)
picker.delegate = self
DispatchQueue.main.async {
present(picker, animated: true, completion: nil)
}
} else {
let imagePickerViewController = UIImagePickerController()
imagePickerViewController.allowsEditing = false
imagePickerViewController.sourceType = .photoLibrary
imagePickerViewController.delegate = self
imagePickerViewController.modalPresentationStyle = .fullScreen
if(Device.isPad) {
imagePickerViewController.modalPresentationStyle = .popover
imagePickerViewController.popoverPresentationController?.sourceView = self.view
imagePickerViewController.popoverPresentationController?.sourceRect = self.view.frame
imagePickerViewController.popoverPresentationController?.permittedArrowDirections = .any
}
DispatchQueue.main.async {
present(picker, animated: true, completion: nil)
}
}
extension ViewController: PHPickerViewControllerDelegate {
@available(iOS 14, *)
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true, completion: nil)
guard !results.isEmpty else { return }
// request image urls
let identifier = results.compactMap(\.assetIdentifier)
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifier, options: nil)
var count = fetchResult.count
fetchResult.enumerateObjects {(asset, index, stop) in
PHAsset.getURL(ofPhotoWith: asset) {[weak self] (url) in
if let url = url {
// got image url
} else {
// show error
}
}
}
}
}
extension PHAsset {
static func getURL(ofPhotoWith mPhasset: PHAsset, completionHandler : @escaping ((_ responseURL : URL?) -> Void)) {
if mPhasset.mediaType == .image {
let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
return true
}
mPhasset.requestContentEditingInput(with: options, completionHandler: { (contentEditingInput, info) in
if let fullSizeImageUrl = contentEditingInput?.fullSizeImageURL {
completionHandler(fullSizeImageUrl)
} else {
completionHandler(nil)
}
})
} else if mPhasset.mediaType == .video {
let options: PHVideoRequestOptions = PHVideoRequestOptions()
options.version = .original
PHImageManager.default().requestAVAsset(forVideo: mPhasset, options: options, resultHandler: { (asset, audioMix, info) in
if let urlAsset = asset as? AVURLAsset {
let localVideoUrl = urlAsset.url
completionHandler(localVideoUrl)
} else {
completionHandler(nil)
}
})
}
}
}
Upvotes: 1