Swift UIImagePickerController problem with photo in iCloud and allowsEditing - swift

I need help.
I use UIImagePickerController to load the avatar. I can take a picture from camera and you can choose a photo.
I have photos stored partly in iCloud, and only previews on the device, partly locally.
When choosing a local photo or from camera, we get to the area selection screen, image cropping.
So if the photo is stored in iCloud, then the following happens:
I select a photo, click done - the window closes, but there is no photo.
My code:
Code for choose photo from library
func openMediaDialog() {
PHPhotoLibrary.requestAuthorization({status in
if status == .authorized{
DispatchQueue.main.async {
self.imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
//self.imagePicker.navigationItem.setHidesBackButton(false, animated: false)
//If you dont want to edit the photo then you can set allowsEditing to false
self.imagePicker.allowsEditing = true
self.imagePicker.delegate = self
self.present(self.imagePicker, animated: true, completion: nil)
}
} else if status == .denied {
self.alertCameraAccessNeeded(title: "Необходим доступ к фото!", message: "Для загрузки аватара необходим доступ к фото. Разрешить?")
}
})
}
DELEGATE:
override func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
/*
Get the image from the info dictionary.
If no need to edit the photo, use `UIImagePickerControllerOriginalImage`
instead of `UIImagePickerControllerEditedImage`
*/
guard let selectedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
self.view.makeToast("Проблема с выбором изображения")
}
print(selectedImage)
....
NEXT STEP - UPLOAD IMAGE
I ask you to tell me how to make sure that the photos are downloaded from icloud, cropped as needed and loaded further according to the usual scenario to the server.

You will get PHAsset if your photos on iCloud.. use this function to get photos
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// it will be loaded asynchronously
loadImageFromPicker(info: info)
picker.dismiss(animated: true, completion: nil)
self.presentingViewController?.dismiss(animated: true, completion: nil)
}
private func loadImageFromPicker(info: [UIImagePickerController.InfoKey : Any]) {
guard let phAsset = info[.phAsset] as? PHAsset else {
return
}
// size doesn't matter, because resizeMode = .none
let size = CGSize(width: 32, height: 32)
let options = PHImageRequestOptions()
options.version = .original
options.deliveryMode = .highQualityFormat
options.resizeMode = .none
options.isNetworkAccessAllowed = true
PHImageManager.default().requestImage(for: phAsset, targetSize: size, contentMode: .aspectFit, options: options) { [weak self] (image, info) in
if let s = self, let image = image {
// use this image
}
}
}

Related

Upload image to Firebase from UIImagePicker

I would like to upload a profile picture to Firebase when my UIImage picker has been chosen. But I don't know how to do it and
I can not understand the documentation, because I'm new in coding). Please, help me. I need to upload picture to Firebase. It will be user picture, so reference to picture should save to Database.
extension ProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
profileImage.image = image
picker.dismiss(animated: true, completion: nil)
}
I don't how to upload and dowload profile image.
Create a storage reference and add folder name and image names.
Storage.storage().reference().child("id").child("profile.png")
and use putData:metadata:completion: method to upload the image. Once image has been uploaded get the image url and update it in user details.
Upload profile image
import FirebaseStorage
import FirebaseAuth
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[.originalImage] as? UIImage, let imageData = image.pngData() {
profileImage.image = image
let storageRef = Storage.storage().reference().child("id").child("profile.png")
let metaData = StorageMetadata()
metaData.contentType = "image/png"
storageRef.putData(imageData, metadata: metaData) { (metaData, error) in
if error == nil, metaData != nil {
storageRef.downloadURL { url, error in
if let url = url {
print(url)//URL of the profile image
self.saveProfileImageUrlInUserDetails(url: url)
}
}
} else {
print(error?.localizedDescription)//upload failed
}
}
}
picker.dismiss(animated: true, completion: nil)
}
Save uploaded photo reference in user detail Update the user's profile
func saveProfileImageUrlInUserDetails(url: URL) {
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.photoURL = url
changeRequest?.commitChanges(completion: { error in
if error == nil {
//saved
} else {
print(error?.localizedDescription)//failed to udpate
}
})
}
Download profile image
if let profileImgUrl = Auth.auth().currentUser?.photoURL?.absoluteString {
let ref = Storage.storage().reference(forURL: profileImgUrl)
ref.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print(error.localizedDescription)
} else if let data = data, let image = UIImage(data: data) {
self.profileImage.image = image
}
}
}

Picking a video which is not of type mov from gallery

Picking a video which is not of type mov from gallery.
I have the following code, which works for videos which are taken from an iPhone. However if I have an image of type mov which I save to my phone and try to choose that, nothing happens. The app doesn't crash but didFinishPicking is not triggered. The app freezes and the cancel button does not work either.
code so far:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any])
{
dismiss(animated: true)
{
if let mediaType = info[UIImagePickerControllerMediaType] as? NSString {
if mediaType == kUTTypeImage, let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
{
//do something
}else if mediaType == kUTTypeMovie
{
//do something else
}
DispatchQueue.main.async {
self.updateProgress()
self.collection.reloadData()
}
}
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController)
{
dismiss(animated: true, completion: nil)
}
The delegate is set in viewDidLoad as:
iPicker.delegate = self
My ultimate aim is to support:
"zip","doc","msg", "jpg","jpeg","avi","pps", "gif", "png", "xls", "csv", "pdf", "txt", "xls", "ppt", "tiff", "tif", "dwg"

Getting location details from image in ios swift

I am trying to get location details from image using
UIImagePickerControllerReferenceURL but I found that PHAsset.fetchAssets(withALAssetURLs: [URL], options: opts) has been deprecated .Please help me in getting location details.
Can we do it using PHAssetCollection?. If so please help me
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
print(info)
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
selectedImage.contentMode = .scaleAspectFit
selectedImage.image = chosenImage
dismiss(animated:true, completion: nil)
if let URL = info[UIImagePickerControllerReferenceURL] as? URL {
let opts = PHFetchOptions()
opts.fetchLimit = 1
let assets = PHAsset.fetchAssets(withALAssetURLs: [URL], options: opts)
let asset = assets[0]
print(asset.location)
// The location is "asset.location", as a CLLocation
// ... Other stuff like dismiss omitted
}
}
Only solution I found so far is to use the iOS 10 code block even in iOS 11 and just ignore the UIImagePickerControllerReferenceURL deprecated message (the key still exists and works in iOS 11)
import AssetsLibrary
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL{
print(imageUrl.absoluteString) //"assets-library://asset/asset.JPG?id=ED7AC36B-A150-4C38-BB8C-B6D696F4F2ED&ext=JPG"
// access image from URL
let assetLibrary = ALAssetsLibrary()
assetLibrary.asset(for: imageUrl as URL! , resultBlock: { (asset: ALAsset!) -> Void in
if let actualAsset = asset as ALAsset? {
let assetRep: ALAssetRepresentation = actualAsset.defaultRepresentation()
let iref = assetRep.fullResolutionImage().takeUnretainedValue()
let image = UIImage.init(cgImage: iref)
self.img.image = image
}
}, failureBlock: { (error) -> Void in
})
}
dismiss(animated: true, completion: nil)
}
Hope this will help.

xcode 8.1 & iOS 10.1.1 "[Generic] Creating an image format with an unknown type is an error" for UIImagePickerController

Trying to allow a user to select a photo from their photo library and then display that image in a UIImageView. Photo library is showing up just fine, but when I select a photo from my library, I get this error "[Generic] Creating an image format with an unknown type is an error".
Stepped through my code below but the error comes up only when selecting an image which does not occur inside either of these 2 functions.
#IBAction func openPhotoLibraryButton(sender: UIButton) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary;
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage!
let imageData = UIImageJPEGRepresentation(image!, 0.6)
let compressedJPGImage = UIImage(data: imageData!)
imagePicked.image = compressedJPGImage
}
Tried the solutions suggested here: xCode 8 - Creating an image format with an unknown type is an error but none of them worked, and it sounds like several folks did not get this issue resolved. Any ideas?
did you try adding _ before picker? I believe the method was changed and the one you are using is deprecated, you should be able to let it autocomplete.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
if let imageData = UIImageJPEGRepresentation(image, 0.6) {
let compressedJPGImage = UIImage(data: imageData)
imagePicked.image = compressedJPGImage
}
} else {
print("Image Picker Failure")
//handle any possible image picker issues/failures so that app doesn't crash in the future
//troubleshoot further if it always hits this
}
dismissViewControllerAnimated(true, completion: nil)
}

Where is the image captured from iOS?

When using the default camera in swift, I use this to take the picture and then show it in an imageView:
#IBAction func takePhoto() {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .Camera
self.presentViewController(picker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
dismissViewControllerAnimated(true, completion: nil)
}
But I want to take the image that I just took and store that image in a constant, but I don't know what is the image I took. I have tried using this as the image
UIImage(named: UIImagePickerControllerOriginalImage)
UIImage(named: "spect a string here") and UIImagePickerControllerOriginalImage returns me a string so that is why I thought that could be the image, but it seems that it won't work.
You can say something like:
var photo = UIImage() // Accessible from anywhere in the class
#IBAction func takePhoto() {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .Camera
self.presentViewController(picker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
photo = info[UIImagePickerControllerOriginalImage] as? UIImage // Assign `photo` to the image
}
In the above code, photo is a variable accessible from anywhere in the class. Therefore, it is accessible from all of your functions and handlers. info[UIImagePickerControllerOriginalImage] as? UIImage is the image from the camera, and in the code, you're changing the variable photo to the image from the camera. Now, the image from the camera is available later from anywhere in that class.