Nijosh
Nijosh

Reputation: 65

Image picker ViewController app stuck - NSXPCConnection

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

Answers (1)

Giang
Giang

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

Related Questions