Had this working on the last few versions of iOS but on 14 cannot get this to work, I have spent the past 5 days Googling.
Whenever I go to add an image from the gallery the popup to select an image is blank.
I have tried UIImagePickerController(which works fine iOS13 and below) and the new PHPickerViewController.
What has been working up until iOS14 is the user clicks a bar button to "add image" and the pop up asks to pick from the gallery and then presents the picker with images in your gallery.
I have set the Info.plist "Privacy - Photo Library Usage Description" for UIImagePickerController, I know the PHPickerViewController doesn't need perms as it handles getting the image for you.
I have also been seeing these purple warning now and again saying "xxxx must be used from main thread only", never seen that before until the new Xcode.
Any help would be much appreciated. Running Xcode 12.0.1 (12A7300), simulators running iOS14.
Adam
class AddCustomExerciseViewController: UIViewController, UITextViewDelegate, UINavigationControllerDelegate, GADBannerViewDelegate, UIImagePickerControllerDelegate, PHPickerViewControllerDelegate{
let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in self.openGallery() }))
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
func openGallery()
{
let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
switch photoAuthorizationStatus {
case .authorized:
self.showGallery()
print("Access is granted by user")
case .notDetermined:
PHPhotoLibrary.requestAuthorization({
(newStatus) in
print("status is \(newStatus)")
if newStatus == PHAuthorizationStatus.authorized {
self.showGallery()
print("success")
}
})
print("It is not determined until now")
case .restricted:
// same same
print("User do not have access to photo album.")
case .denied:
// same same
print("User has denied the permission.")
case .limited:
// same same
print("User has denied the permission.")
}
}
func showGallery()
{
if #available(iOS 14, *)
{
var configuration = PHPickerConfiguration()
configuration.filter = .images
configuration.selectionLimit = 0
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
self.present(picker, animated: true, completion: nil)
}
else
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = false
imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "Warning", message: "You don't have permission to access gallery.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
//get the file url
if let fileUrl = info[UIImagePickerControllerImageURL] as? URL {
print(fileUrl)
print(fileUrl.lastPathComponent)
let filePath = fileUrl.lastPathComponent
if(filePath.hasSuffix("GIF")||filePath.hasSuffix("gif"))
{
//to change later to support gifs
gifView.image = pickedImage
}
else
{
//to show the static image to users
gifView.image = pickedImage
}
//for saving the file name to retrieve in local parse datastore
imageNameToSave = fileUrl.lastPathComponent
}
//for saving the selected image
imageToSave = pickedImage
}
picker.dismiss(animated: true, completion: nil)
}
@available(iOS 14, *)
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult])
{
picker.dismiss(animated: true, completion: nil)
for result in results
{
result.itemProvider.loadObject(ofClass: UIImage.self, completionHandler: { (object, error) in
if let image = object as? UIImage {
DispatchQueue.main.async {
// Use UIImage
print("Selected image: \(image)")
}
}
})
}
} }
On iOS 14 the restricted image picker permission dialog opens in a separate thread, so when the authorization return you will need to perform UI tasks on main thread.