Getting location details from image in ios swift - 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.

Related

Cannot assign value of type 'Foundation.Data' to type 'Appname.Data'

I have code for fetching the image data.The same code works fine in other projects but in this project i am getting this error.The code which causes the error is as given below:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let imageURL = info[UIImagePickerController.InfoKey.imageURL] as? URL
let imagePath = imageURL?.path
print("imagepath is",imagePath)
_ = imageURL?.lastPathComponent
// self.camimgname = imageName
// self.finalimgname = self.camimgname
var chosenImage = UIImage()
chosenImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage //2
self.profileimg.contentMode = .scaleAspectFit //3
self.profileimg.image = chosenImage //4
if let data = chosenImage.jpegData(compressionQuality: 0.5) {
// self.camdata = data
self.imgdata = data
}
dismiss(animated:true, completion: nil)
}
The screenshot of the error is as given below:
What could be the issue with this Data.Is there any unwanted framework added or anything?

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
}
}
}

didFinishPickingMediaWithInfo function goes on infinite loop

It looks like the didFinishPickingMediaWithInfo function is going on an infinite loop and it eventually crashes with an error that says in the console:
warning: could not execute support code to read Objective-C class data in >the process. This may reduce the quality of type information available.
Right when I record a video and press the choose button, it crashes because it calls the didFinishPickingMediaWithInfo. Here is the relevant code:
let imagePicker: UIImagePickerController! = UIImagePickerController()
let saveFileName = "/test.mp4"
if (UIImagePickerController.isSourceTypeAvailable(.camera)) {
if UIImagePickerController.availableCaptureModes(for: .rear) != nil {
//if the camera is available, and if the rear camera is available, the let the image picker do this
imagePicker.sourceType = .camera
imagePicker.mediaTypes = [kUTTypeMovie as String]
imagePicker.allowsEditing = false
imagePicker.delegate = self as? UIImagePickerControllerDelegate & UINavigationControllerDelegate
imagePicker.videoMaximumDuration = 60
imagePicker.videoQuality = .typeIFrame1280x720
present(imagePicker, animated: true, completion: nil)
} else {
postAlert("Rear camera doesn't exist", message: "Application cannot access the camera.")
}
} else {
postAlert("Camera inaccessable", message: "Application cannot access the camera.")
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print(123)
imagePickerController(imagePicker, didFinishPickingMediaWithInfo: [saveFileName : kUTTypeMovie])
let videoURL = info[UIImagePickerControllerReferenceURL] as? NSURL
print("\(String(describing: videoURL))" )
guard let path = videoURL?.path else { return }
let videoName = path.lastPathComponent
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentDirectory = paths.first as String!
let localPath = documentDirectory! + "/" + videoName
guard let imageData = NSData(contentsOfFile: localPath) else { return }
let image = UIImage(data: imageData as Data)
picker.dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
self.imagePicker.delegate = self
}
Thank you in advance!
You are calling the function from inside of itself, here:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print(123)
imagePickerController(imagePicker, didFinishPickingMediaWithInfo: [saveFileName : kUTTypeMovie])
That is causing your infinite loop.

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)
}

Save image in Realm

I'm trying to pick image from device's Photo Library in method:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
userPhoto.image = info[UIImagePickerControllerOriginalImage] as! UIImage?
userPhoto.contentMode = .scaleAspectFill
userPhoto.clipsToBounds = true
dismiss(animated: true, completion: nil)
}
and save this picture in Realm (as NSData):
asset.assetImage = UIImagePNGRepresentation(userPhoto.image!)! as NSData?
...
try! myRealm.write
{
user.assetsList.append(asset)
myRealm.add(user)
}
After build succeeded and trying to pick and save image (in the app) i have app error:
'Binary too big'
What i'm doing wrong?
P.S. Sorry for my English :)
After some actions i have this code. But it's overwrite my image.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
let imageUrl = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = imageUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
let image = info[UIImagePickerControllerOriginalImage]as! UIImage
let data = UIImagePNGRepresentation(image)
do
{
try data?.write(to: localPath!, options: Data.WritingOptions.atomic)
}
catch
{
// Catch exception here and act accordingly
}
userPhoto.image = image
userPhoto.contentMode = .scaleAspectFill
userPhoto.clipsToBounds = true
urlCatch = (localPath?.path)!
self.dismiss(animated: true, completion: nil);
}
Don't save the image itself into realm, just save the location of the image into realm as String or NSString and load the image from that saved path. Performance wise it's always better to load images from that physical location and your database doesn't get too big
func loadImageFromPath(_ path: NSString) -> UIImage? {
let image = UIImage(contentsOfFile: path as String)
if image == nil {
return UIImage()
} else{
return image
}
}
or you just save the image name, if it's in your documents directory anyhow
func loadImageFromName(_ imgName: String) -> UIImage? {
guard imgName.characters.count > 0 else {
print("ERROR: No image name")
return UIImage()
}
let imgPath = Utils.getDocumentsDirectory().appendingPathComponent(imgName)
let image = ImageUtils.loadImageFromPath(imgPath as NSString)
return image
}
and here a rough example how to save a captured image to your directory with a unique name:
#IBAction func capture(_ sender: AnyObject) {
let videoConnection = stillImageOutput?.connection(withMediaType: AVMediaTypeVideo)
stillImageOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (imageDataSampleBuffer, error) -> Void in
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
//self.stillImage = UIImage(data: imageData!)
//self.savedImage.image = self.stillImage
let timestampFilename = String(Int(Date().timeIntervalSince1970)) + "someName.png"
let filenamePath = URL(fileReferenceLiteralResourceName: getDocumentsDirectory().appendingPathComponent(timestampFilename))
let imgData = try! imageData?.write(to: filenamePath, options: [])
})
/* helper get Document Directory */
class func getDocumentsDirectory() -> NSString {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
//print("Path: \(documentsDirectory)")
return documentsDirectory as NSString
}
https://realm.io/docs/objc/latest/#current-limitations
maximum data size is 16 MB . this is limitation of realm
Depending on how your serializing the image data (for example if it's a lossless bitmap), it's quite possible that this data exceed 16MB, which as you've stated is Realm's maximum supported size for binary properties.
When you invoke NSData.length, how large does it say your data is?