I have this code:
@IBAction func importButtonPressed(_ sender: Any) {
self.imagePicker.sourceType = .photoLibrary
self.imagePicker.allowsEditing = true
self.imagePicker.mediaTypes = [kUTTypeMovie as String, kUTTypeImage as String]
self.present(self.imagePicker,animated: true, completion: nil)
}
This presents the UIImagePicker perfectly. Then when I want to use the picked item to get say the date of the PHAsset:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard info[UIImagePickerControllerMediaType] != nil else { return }
let mediaType = info[UIImagePickerControllerMediaType] as! CFString
switch mediaType {
case kUTTypeImage:
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
...
}
break
case kUTTypeMovie:
if let videoURL = info[UIImagePickerControllerMediaURL] as? URL, let pickedAsset = info[UIImagePickerControllerPHAsset] as? PHAsset {
print("kUTTypeMovie")
MyVariables.isScreenshot = false
let creationDate = pickedAsset.creationDate
print(creationDate,"creationDate")
}
break
case kUTTypeLivePhoto:
print("livePhoto")
dismiss(animated: true, completion: nil)
break
default:
dismiss(animated: true, completion: nil)
print("something else")
break
}
}
Now, when I pick a video for instance,print("kUTTypeMovie")
fails I think because let pickedAsset = info[UIImagePickerControllerPHAsset] as? PHAsset
fails
Elsewhere (UIImagePickerControllerDelegate get date from picked image in iOS 11) I have seen that perhaps this is because I need authorization to pick PHAssets.
So I change my first block of code to:
@IBAction func importButtonPressed(_ sender: Any) {
let status = PHPhotoLibrary.authorizationStatus()
switch status {
case .authorized:
PHPhotoLibrary.requestAuthorization({status in
if status == .authorized {
self.imagePicker.sourceType = .photoLibrary
self.imagePicker.allowsEditing = true
self.imagePicker.mediaTypes = [kUTTypeMovie as String, kUTTypeImage as String]
self.present(self.imagePicker,animated: true, completion: nil)
}
})
case .denied:
print("denied")
// probably alert the user that they need to grant photo access
case .notDetermined:
print("not determined")
case .restricted:
print("restricted")
// probably alert the user that photo access is restricted
}
}
However now when I press the import button it crashes with an lldb error:
libsystem_kernel.dylib`__abort_with_payload:
0x1854f7040 <+0>: mov x16, #0x209
0x1854f7044 <+4>: svc #0x80
-> 0x1854f7048 <+8>: b.lo 0x1854f7060 ; <+32>
0x1854f704c <+12>: stp x29, x30, [sp, #-0x10]!
0x1854f7050 <+16>: mov x29, sp
0x1854f7054 <+20>: bl 0x1854d8bdc ; cerror_nocancel
0x1854f7058 <+24>: mov sp, x29
0x1854f705c <+28>: ldp x29, x30, [sp], #0x10
0x1854f7060 <+32>: ret
So clearly I am not doing that correctly. How am I supposed to do this?
The crash is because of the below missing permission to access the photo library,
This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data.
In your Info.plist
, add NSPhotoLibraryUsageDescription
key with some description as below and it will work fine
Edit You should also use the PhotoLibrary
authorization in proper way as below.
@IBAction func importButtonPressed(_ sender: Any) {
PHPhotoLibrary.requestAuthorization({status in
switch status {
case .authorized:
self.imagePicker.sourceType = .photoLibrary
self.imagePicker.allowsEditing = true
self.imagePicker.mediaTypes = [kUTTypeMovie as String, kUTTypeImage as String]
self.present(self.imagePicker,animated: true, completion: nil)
case .denied:
print("denied")
// probably alert the user that they need to grant photo access
case .notDetermined:
print("not determined")
case .restricted:
print("restricted")
// probably alert the user that photo access is restricted
}
})
}