use of unresolved identifier 'info' apple tutorial - ios

I'm working on this app development tutorial:
https://developer.apple.com/library/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson4.html#//apple_ref/doc/uid/TP40015214-CH6-SW1
and I got up to the part where you use the info dictionary (towards the end of the tutorial), but I'm getting the error "use of unresolved identifier 'info'". I copied and pasted the code they provided:
//The info dictionary contains multiple representations of the image,
//and this uses the original.
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
but it wont work

The code is supposed to be placed in this method:
func imagePickerController(picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : AnyObject]) {
}
info is one of the parameters to the function.

Related

Getting metadata of image from photoLibrary

I need to get the metaData from an Image I'm picking via UIImagePickerController.
This is my code:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let metaData = info[UIImagePickerController.InfoKey.mediaMetadata] as? [AnyHashable: Any]
print(metaData)
picker.dismiss(animated: true, completion: nil)
}
It works fine, when im picking the Image having .camera as source. But when I use .photoLibrary as source, then metaData is nil. I already read through other questions and tried stuff like
let asset = info[.phAsset] as? PHAsset
print(asset?.creationDate ?? "None")
print(asset?.location ?? "None")
But this also returns nil. I guess the source of the problem is, that the info-Dictionary only returns 4 Keys when picking from .photoLibrary:
UIImagePickerControllerOriginalImage
UIImagePickerControllerMediaType
UIImagePickerControllerImageURL
UIImagePickerControllerReferenceURL
It would be awesome if someone could tell me where my mistake is.
Thanks in advance !
I had the same problem. If the user does not grant access to the photo library first, info[.phAsset] will return nil.
Quote from Apple: "Accessing the photo library always requires explicit permission from the user. The first time your app uses PHAsset, PHCollection, PHAssetCollection, or PHCollectionList methods to fetch content from the library ..."
Thus, you have to call PHPhotoLibrary.requestAuthorization{ ... } before presenting the image picker.
If the user denies the request, info[.phAsset] will also be nil!
This key is valid only when using an image picker whose source type is set to UIImagePickerController.SourceType.camera, and applies only to still images.
The value for this key is an NSDictionary object that contains the metadata of the photo that was just captured. To store the metadata along with the image in the Camera Roll, use the PHAssetChangeRequest class from the Photos framework.
https://developer.apple.com/documentation/uikit/uiimagepickercontroller/infokey/1619147-mediametadata

UIImagePickerControllerDelegate get date from picked image in iOS 11

UIImagePickerControllerReferenceURL was deprecated in iOS 11 (even though it's still returned in the info dictionary) and was supposed to be replaced with UIImagePickerControllerPHAsset, but I've yet to get an info dictionary back which contains that key. Since the one is deprecated and the other is missing, is there a known solution for extracting the "date taken" from the picked image?
For reference, this is an example info dictionary returned when and image is picked from the library:
▿ 4 elements
▿ 0 : 2 elements
- key : "UIImagePickerControllerImageURL"
- value : file:///private/var/mobile/Containers/Data/Application/EE1BA60E-2DC3-47C5-A58D-86498E95C323/tmp/3A025D4C-B378-474B-8A09-017479A3A776.jpeg
▿ 1 : 2 elements
- key : "UIImagePickerControllerMediaType"
- value : public.image
▿ 2 : 2 elements
- key : "UIImagePickerControllerReferenceURL"
- value : assets-library://asset/asset.HEIC?id=537976CD-A550-41C9-9416-92C8072112D7&ext=HEIC
▿ 3 : 2 elements
- key : "UIImagePickerControllerOriginalImage"
- value : <UIImage: 0x1d04b4760> size {3024, 4032} orientation 3 scale 1.000000
(Note that UIImagePickerControllerReferenceURL is still present, though deprecated, and the suggested replacement, UIImagePickerControllerPHAsset, is missing.)
If it were present, getting the date would be simple:
if let asset = info[UIImagePickerControllerPHAsset] as? PHAsset,
let resource = PHAssetResource.assetResources(for: asset).first {
let dateTaken = resource.creationDate
}
Could it be that Apple forgot to implement UIImagePickerControllerPHAsset? Any ideas on workarounds (without using deprecated methods)?
Note on possible duplicates
I believe that previous solutions on Stack Overflow are deprecated, and thus won't answer the question using modern approaches.
Swift 4.1
I struggled with this for a while too. It turns out you just need user permission to access to the photo library - then info will contain a value for the key UIImagePickerControllerPHAsset. You can check & request access like this:
let status = PHPhotoLibrary.authorizationStatus()
switch status {
case .authorized:
// show your media picker
case .denied:
// probably alert the user that they need to grant photo access
case .notDetermined:
PHPhotoLibrary.requestAuthorization({status in
if status == .authorized {
// show your media picker
}
})
case .restricted:
// probably alert the user that photo access is restricted
}
Then you use the imagePickerController(_: didFinishPickingMediaWithInfo:) method as usual and will have access to the UIImagePickerControllerPHAsset
You can get the date by examining the chosen photo's metadata through the ImageIO framework.
However, the claim that the PHAsset information doesn't arrive is simply bogus. It arrives just fine. You didn't show your code, so who knows what you're doing? Perhaps the problem is that you forgot to get user authorization? Without user authorization, of course you can't access the PHAsset. You'll get the UIImagePickerControllerOriginalImage and the UIImagePickerControllerImageURL and that's all.
This code works just fine for me (assuming we have the necessary user authorization before using the image picker controller in the first place):
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : Any]) { //
let asset = info[UIImagePickerControllerPHAsset] as? PHAsset
let url = info[UIImagePickerControllerMediaURL] as? URL
var im = info[UIImagePickerControllerOriginalImage] as? UIImage
if let ed = info[UIImagePickerControllerEditedImage] as? UIImage {
im = ed
}
let live = info[UIImagePickerControllerLivePhoto] as? PHLivePhoto
let imurl = info[UIImagePickerControllerImageURL] as? URL
self.dismiss(animated:true) {
if let style = asset?.playbackStyle { // and so on, works fine
// ....
}
}
}

Swift 3, SDwebimage - How do you set a button placeholder image on image upload with SDWebImage?

I'm creating the ability for users to upload an image using buttons with the image as the background. What I'm trying to do is set "imgTemp" which was the image the user chose from their phone and set it to the background of the button using sdwebimage. How would you do this with no errors? Im getting "Cannot convert value of type 'UIImage?' to expected argument type 'URL?'" which I understand just don't have a clue how to fix it. Thanks.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]){
let imgTemp = info[UIImagePickerControllerOriginalImage] as? UIImage
cell.image01.sd_setBackgroundImage(with: imgTemp, for: UIControlState.normal, placeholderImage: defaultImg)
}
Since the value contained within the UIImagePickerControllerOriginalImage key is a UIImage object you can directly set it as a background image. You do not need to use a method provided by SDWebImage for the same.
cell.image01.setBackgroundImage(imgTemp, for: .normal)
SDWebImage is used for asynchronously loading an image from a given URL.

iOS Swift - Not able to use video from Library

I'm trying to obtain a video from the library in my swift app.
I'm using the following code snippet :
print("ChatDetailsController - imgaction - Vid from Lib pressed")
self.selection = "videoLib";
self.imgSelection = "vidFromLib"
self.imagePicker.sourceType = .PhotoLibrary
self.imagePicker.delegate = self
self.imagePicker.mediaTypes = ["public.movie"]
self.presentViewController(self.imagePicker!, animated: true, completion: nil)
Then in delegate method:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
if(selection == "videoLib")
{
if let videoURL = info[UIImagePickerControllerReferenceURL] as? NSURL
{
print("imagePickerController - reached for video - from Lib - \(videoURL)")
let videoData = NSData(contentsOfURL: videoURL)
}
}
}
When running the app, it shows the library and I can select a video, then it says compressing video.. but then the app crashes.
The Crash happens when I try to access the videoData Variable becuase it wasn't able to get the actual data since the path is an asset path and not a video path.
The Log shows something similar to this:
fatal error: unexpectedly found nil while unwrapping an Optional value
The print function shows:
imagePickerController - reached for video - from Lib - assets-library://asset/asset.MOV?id=7D3BFA00-A7CB-470C-8899-F82FCC2CBC54&ext=MOV
Also, right after choosing/selecting the video, a message similar to this is displayed in the console/log:
[Generic] video path /var/mobile/Media/PhotoData/CPLAssets/group419/A2901DD1-FDEF-423B-B4A3-E808B9AC45E1.MOV for PLPreviewImageAndDurationForVideoAtPath does not exist
Of course the file name changes on every run.
I'm able to get a video and images from the camera, and getting images from the library, I'm only having trouble with using the the video from the library. I would expect to see the video URL similar to :
/var/mobile/Containers/Data/Application/BEDDC883-B20E-496D-8C9A-A40EC0A29214/Documents/63ea24932c101b76c72fcbae3993fc9b.mov for example; where the video file is in the application and not showing as an unusable asset URL.
Any help would be appreciated.
The problem is that you're trying to fetch the wrong video. You're trying to use info[UIImagePickerControllerReferenceURL]. What you want is info[UIImagePickerControllerMediaURL].

UIImagePickerControllerReferenceURL returns nil, crashing the app

I'm trying to print all the image metadata in the imagePickerController: didFinishPickingMediaWithInfo function. When I use the info.objectForKey(UIImagePickerControllerReferenceURL) method, it returns nil and if try to use this result my app crashes. Does anyone know why it returns nil and what else can I use to print all the image metadata when I pick an image? (using UIImageJPEGRepresentation is not an option because the EXIF data is removed).
This is my code:
func imagePickerController(picker: UIImagePickerController!, didFinishPickingMediaWithInfo info: NSDictionary!)
{
let image = info.objectForKey(UIImagePickerControllerOriginalImage) as UIImage
let refURL : NSURL = info.objectForKey(UIImagePickerControllerReferenceURL) as NSURL
var localSourceRef: CGImageSourceRef = CGImageSourceCreateWithURL(refURL, nil)
var localMetadata: NSDictionary = CGImageSourceCopyPropertiesAtIndex(localSourceRef, 0, nil)
println("\n Photo data: \n")
println(localMetadata)
}
So it sounds like there are actually two questions here:
1) Why is UIImagePickerControllerReferenceURL returning a nil reference?
2) How can you get location data from the photo?
So, the answer to (1) is usually because you receive the callback didFinishPickingMedia before the OS as written the file to the image library.
The answer to #2 is much trickier, as showcased by this question's line of answers:
Reading the GPS data from the image returned by the camera in iOS iphone
There are a number of variables you need to account for:
iOS will strip the GPS data out if you haven't requested access to location data, so you'll need to prompt for location access using CLLocationManager.
If the user has geotagging disabled, you'll never get GPS coords.
If the phone can't get a GPS lock, iOS won't record the GPS coords.
Per this answer: https://stackoverflow.com/a/10338012/490180 you should be able to retrieve the raw UIImage and then create the CGImageSourceRef from the data property off of UIImage's CGImage. This effectively removes the need for you to ever access the ReferenceURL.

Resources