I would like to edit/compress video after selection like it was in UIImagePickerController with allowsEditing = true.
Still the new PHPickerViewController doesn't have this property and Apple says that there is no such property anymore here. But there are apps in App Store that pushing "allowsEditing controller" after selecting asset from PHPickerViewController
Here is my PHPickerViewController implementation:
func openImagePicker() {
if #available(iOS 14, *) {
var configuration = PHPickerConfiguration()
configuration.preferredAssetRepresentationMode = .automatic
let picker = PHPickerViewController(configuration: configuration)
// Set the delegate
picker.delegate = self
// Present the picker
present(picker, animated: true)
} else {
// Fallback on earlier versions
imagePicker?.photoGalleryAsscessRequest()
}
}
extension EditController: PHPickerViewControllerDelegate {
#available(iOS 14, *)
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
self.dismiss(animated: true)
}
}
I investigated this issue but indeed there is no support for like as you mention allowsediting.
For example related to your question preset values for video edits was depreciated to UIImagePickerController.ImageURLExportPreset.compatible but There is no support for automatic compression. The picker will always pass the original video/image and it is up to the app to do the necessary compressions or edits.
You can check this Apple Document: imageExportPreset.
Apple specifically mentions that we should be using this new one instead of the older UIImagePickerViewController. If someone wonder more : Meet the new Photos picker
Related
I am working on new image picker API provided by Apple in WWDC2020 named as PHPicker. I am getting this error when I select the image form the picker second time. First time the code works perfectly. Second time when I click on the button to open the picker, app crashes with the following error. "Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Picker's configuration is not a valid configuration.'".
#IBAction func addVideo(_ sender: UIButton) {
presentPicker(filter: .videos)
}
private func presentPicker(filter: PHPickerFilter?) {
var configuration = PHPickerConfiguration(photoLibrary: .shared())
// Set the filter type according to the user’s selection.
configuration.filter = filter
// Set the mode to avoid transcoding, if possible, if your app supports arbitrary image/video encodings.
configuration.preferredAssetRepresentationMode = .current
// Set the selection behavior to respect the user’s selection order.
configuration.selection = .ordered
// Set the selection limit to enable multiselection.
configuration.selectionLimit = 1
// Set the preselected asset identifiers with the identifiers that the app tracks.
configuration.preselectedAssetIdentifiers = selectedAssetIdentifiers
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true)
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true)
let existingSelection = self.selection
var newSelection = [String: PHPickerResult]()
for result in results {
let identifier = result.assetIdentifier!
newSelection[identifier] = existingSelection[identifier] ?? result
}
// Track the selection in case the user deselects it later.
selection = newSelection
selectedAssetIdentifiers = results.map(\.assetIdentifier!)
selectedAssetIdentifierIterator = selectedAssetIdentifiers.makeIterator()
if selection.isEmpty {
displayEmptyImage()
} else {
displayImage()
}
}
I am using the same code that is provide by apple on their website.
https://developer.apple.com/documentation/photokit/phpickerviewcontroller. I just have changed the selectionLimit to 1 from 0.
Apparently it is documented (just kidding, it's in a header file) that the preselectedAssetIdentifiers property is only valid when selectionLimit is greater than 1, which is the default.
Here's an answer from the Apple developer forum for reference: https://developer.apple.com/forums/thread/705493
There must be a problem with your code.
I've copy-pasted your solution and it works correctly on Simulator (iOS 15.0).
I am trying to read out some metadata from images which I fetched with the PHPickerViewController.
var config = PHPickerConfiguration()
self.phPicker = PHPickerViewController(configuration: config)
if let picker = self.phPicker {
self.phPicker?.delegate = self
self.present(picker, animated: true) {
self.phPicker = nil
}
}
But the PHPickerResult.assetIdentifier to access those data is always nil.
extension ChatViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true) {
if results.isEmpty {
return
}
assert(results.first!.assetIdentifier != nil) // fails
}
}
}
The trick is the correct configuration of the PHPickerViewController.
var config = PHPickerConfiguration() // WRONG!
let picker = PHPickerViewController(configuration: config)
According to documentation you have to use the PHPhotoLibrary.
A PHPhotoLibrary provides access to the metadata and image data for
the photos, videos and related content in the user's photo library,
including content from the Camera Roll, iCloud Shared, Photo Stream,
imported, and synced from iTunes.
So just use PHPhotoLibrary in the constructor and everything works fine.
var config = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared()) // CORRECT!
let picker = PHPickerViewController(configuration: config)
In WWDC20 apple introduced PHPicker - the modern replacement for UIImagePickerController.
I'm wondering if it's possible to retrieve PHAsset using the new photo picker?
Here is my code:
private func presentPicker(filter: PHPickerFilter) {
var configuration = PHPickerConfiguration()
configuration.filter = filter
configuration.selectionLimit = 0
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true)
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true)
}
I managed to find an answer from the developers of this framework on the apple forum:
Yes, PHPickerResult has the assetIdentifier property which can contain
a local identifier to fetch the PHAsset from the library. To have
PHPicker return asset identifiers, you need to initialize
PHPickerConfiguration with the library.
Please note that PHPicker does not extend the Limited Photos Library
access for the selected items if the user put your app in Limited
Photos Library mode. It would be a good opportunity to reconsider if
the app really needs direct Photos Library access or can work with
just the image and video data. But that really depend on the app.
The relevant section of the "Meet the new Photos picker" session
begins at 10m 20s.
Sample code for PhotoKit access looks like this:
import UIKit
import PhotosUI
class PhotoKitPickerViewController: UIViewController, PHPickerViewControllerDelegate {
#IBAction func presentPicker(_ sender: Any) {
let photoLibrary = PHPhotoLibrary.shared()
let configuration = PHPickerConfiguration(photoLibrary: photoLibrary)
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true)
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
let identifiers = results.compactMap(\.assetIdentifier)
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
// TODO: Do something with the fetch result if you have Photos Library access
}
}
First off I want to say that I'm by no means an experienced Swift programmer, so if I am missing anything for someone to help me debug my issue - then I'm sorry about that. Just drop a comment and I'll add whatever is necessary to help you help me.
I'm following Apple's guide on how to develop iOS apps with Swift (as seen here).
But for some reason I'm getting this warning:
Instance method 'imagePickerController(picker:didFinishPickingMediaWithInfo:)' nearly matches optional requirement 'imagePickerController(_:didFinishPickingMediaWithInfo:)' of protocol 'UIImagePickerControllerDelegate'
I've attempted to suppress the issue by both using #nonobjc and setting it to private. The problem is that the new image isn't taking the old image's place. Instead it gives me this error in the output:
[Generic] Creating an image format with an unkown type is an error.
This is the code that concerns my tapGesture and the imagePicking:
// MARK: UIImagePickerControllerDelegate
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// The info dictionary contains multiple representations of the image, and this uses the original.
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
// Set photoImageView to display the selected image.
photoImageView.image = selectedImage
// Dismiss the picker.
dismiss(animated: true, completion: nil)
}
// MARK: Actions
#IBAction func selectTapGestureFromPhotoLibrary(_ sender: UITapGestureRecognizer) {
// Hide the keyboard
nameTextField.resignFirstResponder()
// UIImagePickerController allows users to pick media from their photo library!
let imagePickerController = UIImagePickerController()
// Only allow photos to be picked, not taken
imagePickerController.sourceType = .photoLibrary
imagePickerController.delegate = self
present(imagePickerController, animated: true, completion: nil)
}
If my question isn't clear enough I need help figuring out why the image in my app isn't changing - even though I've followed the guide. I've already noticed some issues that I assume has to do with Xcode having been updated, but not the guide.
It might be worth mentioning that I have already set the info.plist to allow me to access all the necessary security privileges.
I'm running iOS 10.1 and Xcode 8.1
Found a similar issue that together with #Larme's comment helped me solve it:
Similar issue
The code is correct, Please check and sure that you have connect all the necessary outlets.
I am trying to follow a recent post on using a MPMediaPickerControllerDelegate to present a music selection list.
The tutorial is found at this URL:
http://www.justindoan.com/tutorials/
I am using this code:
import UIKit
import MediaPlayer
class ViewController: UIViewController, MPMediaPickerControllerDelegate {
var mediapicker1: MPMediaPickerController!
override func viewDidLoad() {
super.viewDidLoad()
let mediaPicker: MPMediaPickerController = MPMediaPickerController.self(mediaTypes:MPMediaType.music)
mediaPicker.allowsPickingMultipleItems = false
mediapicker1 = mediaPicker
mediaPicker.delegate = self
self.presentViewController(mediapicker1, animated: true, completion: nil)
}
}
However I have found that the:
self.presentViewController(mediapicker1, animated: true, completion: nil)
does not work. Unfortunately, Swift 3's suggested automatic solution does not work either:
self.present(mediapicker1, animated: true, completion: nil)
Furthermore, the iOS 10 Beta Release Notes, found at:
https://www.scribd.com/doc/315770725/IOS-10-Beta-Release-Notes
says on page 10 of 18,
An MPMediaPickerController object may not display as expected.
I have spent a great deal of time looking to solve this issue on my own with no success.
Any suggestions?
Go through the steps:
Add 'NSAppleMusicUsageDescription' to your Info.plist for the privacy authority.
Make sure your Music app is available in your iPhone. It will not work in the simulator.
As per our discussion over comments, I recently use the MPMediaPickerController in my latest app named playmates. I am sharing the working code with you. I have written the self-explanatory code.
import MediaPlayer
class viewControllerName: UIViewController,MPMediaPickerControllerDelegate {
//Below is Inaction for picking music from media library
#IBAction func btnMediaPickerAction(_ sender: UIButton) {
let mediaPicker: MPMediaPickerController = MPMediaPickerController.self(mediaTypes:MPMediaType.music)
mediaPicker.delegate = self
mediaPicker.allowsPickingMultipleItems = false
self.present(mediaPicker, animated: true, completion: nil)
}
// MPMediaPickerController Delegate methods
func mediaPickerDidCancel(_ mediaPicker: MPMediaPickerController) {
self.dismiss(animated: true, completion: nil)
}
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
self.dismiss(animated: true, completion: nil)
print("you picked: \(mediaItemCollection)")//This is the picked media item.
// If you allow picking multiple media, then mediaItemCollection.items will return array of picked media items(MPMediaItem)
}
}
I found below discripencies in your code:
use self.present not self.presentViewController
No need to create global instance of mediaPicker. As in the delegate method you are getting the instance of MPMediaPickerController
Add Privacy - Media Library Usage Description in info.plist