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.
Related
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
In my application I found a memory leak when I used the UIImagePickerController, I thought it was my application, but searching for a solution I found an Apple's sample and I also found that this sample has the same memory leak.
You can find the example in the following URL.
https://developer.apple.com/library/content/samplecode/PhotoPicker/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010196
According to the UIImagePickerController documentation:
https://developer.apple.com/documentation/uikit/uiimagepickercontroller
In point 5, thy said that you have to dismiss the image picker using your delegate object, in the Apple's sample the UIImagePickerDelegate is doing the dismiss.
The issue is that the memory leak is wasting approximately 21 MB of memory when you select an image and work with it.
Used Memory without Memory Leak
Used Memory with Memory Leak
Memory Leak
This is the code to present the UIImagePickerController:
#IBAction func showImagePickerForPhotoPicker(_ sender: UIBarButtonItem) {
showImagePicker(sourceType: UIImagePickerControllerSourceType.photoLibrary, button: sender)
}
fileprivate func showImagePicker(sourceType: UIImagePickerControllerSourceType, button: UIBarButtonItem) {
// If the image contains multiple frames, stop animating.
if (imageView?.isAnimating)! {
imageView?.stopAnimating()
}
if capturedImages.count > 0 {
capturedImages.removeAll()
}
imagePickerController.sourceType = sourceType
imagePickerController.modalPresentationStyle =
(sourceType == UIImagePickerControllerSourceType.camera) ?
UIModalPresentationStyle.fullScreen : UIModalPresentationStyle.popover
let presentationController = imagePickerController.popoverPresentationController
presentationController?.barButtonItem = button // Display popover from the UIBarButtonItem as an anchor.
presentationController?.permittedArrowDirections = UIPopoverArrowDirection.any
if sourceType == UIImagePickerControllerSourceType.camera {
// The user wants to use the camera interface. Set up our custom overlay view for the camera.
imagePickerController.showsCameraControls = false
// Apply our overlay view containing the toolar to take pictures in various ways.
overlayView?.frame = (imagePickerController.cameraOverlayView?.frame)!
imagePickerController.cameraOverlayView = overlayView
}
present(imagePickerController, animated: true, completion: {
// Done presenting.
})
}
And this is the code in the delegate to dismiss the UIImagePickerController:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage]
capturedImages.append(image as! UIImage)
if !cameraTimer.isValid {
// Timer is done firing so Finish up until the user stops the timer from taking photos.
finishAndUpdate()
} else {
dismiss(animated: true, completion: nil)
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: {
// Done cancel dismiss of image picker.
})
}
fileprivate func finishAndUpdate() {
dismiss(animated: true, completion: { [weak self] in
guard let `self` = self else {
return
}
if `self`.capturedImages.count > 0 {
if self.capturedImages.count == 1 {
// Camera took a single picture.
`self`.imageView?.image = `self`.capturedImages[0]
} else {
// Camera took multiple pictures; use the list of images for animation.
`self`.imageView?.animationImages = `self`.capturedImages
`self`.imageView?.animationDuration = 5 // Show each captured photo for 5 seconds.
`self`.imageView?.animationRepeatCount = 0 // Animate forever (show all photos).
`self`.imageView?.startAnimating()
}
// To be ready to start again, clear the captured images array.
`self`.capturedImages.removeAll()
}
})
}
I'm still looking for a solution, any help will be appreciated.
I had the same issue. So did a ton of other people. Dating back to 2008. Pretty crazy.
http://iphonedevsdk.com/forum/iphone-sdk-development/3816-uiimagepickercontroller-memory-issues.html
UIImagePickerController leaking memory after launch and during taking a picture. Makes app crash after taking more than a 100 pictures
UIImagePickerController Memory Leak
Unfortunately, the best answer I could find was to use a singleton, which sucks. [i.e. Intentionally retain an instance of UIImagePickerController so you just access that every single time you want to select an image.] This is what others have suggested.
Further, I just spent an hour writing this answer with code that uses a singleton, and I just could not avoid a memory leak [although I thought I had for a second]. Maybe I'm just doing it incorrectly - feel free to try. But I won't post my dysfunctional code as an answer.
The best answer [which is how I solved my problem] is to use a third party pod/library. I used ImagePicker, and it is quick, fast, FREE, beautiful, and NO memory leaks! [MIT License]
Check it out here:
https://github.com/hyperoslo/ImagePicker
I know there are similar questions available on SO.
The reason why I'm starting a new topic.
I want to take multiple photos and save them into an array for later usage (when user finished taking photos)
I already read the API about showsCameraControl, takePicture() and cameraOverlayView
I managed already to capture multiple photos but I have always to confirm every photo with the "Retake/Use Photo" screen. When tipping on Use Photo, the App saves it into the array.
The same way is already working in the Workflow App from DeskConnect. They have a workflow "Take Photo" where you can choose how many photos you want to take. And they are (in my eyes) using Apple's default controls
Any help is appreciated.
Doesn't matter if it's a solution to avoid "Retake/Use Photo" or to create a custom overly view. For me it is important to keep Apple's default controls so the user feels comfortable with the well known controls.
(I also already took a look on the tutorials Apple provides).
My code so far
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
openCamera()
}
func openCamera() {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
imagePicker.allowsEditing = false
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageArray.append(pickedImage)
print(imageArray.count)
}
self.dismiss(animated: true, completion: nil)
openCamera()
}
This question already has answers here:
Swift ImagePickerController didFinishPickingMediaWithInfo not fired
(2 answers)
Closed 6 years ago.
I'm new to swift...
in fact I'm new to Any Apple products. so basically I'm trying to learn how to build and aircraft while trying to fly and learn how to fly it as well. When this disclaimer is out there I'd like some help ;)
My issue is that I cannot get UIImagePickerController to return with an image to me after I've taken one with the Camera. I think I'm missing something fundamental or at least something important to make it work ;)
But I cannot for the life of me figure out where I'm doing it wrong.
this is what I think is the relevant parts of my ViewController however do ask if you feel I'm leaving something important out:
#IBAction func shootPhoto(_ sender: UIButton) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
picker.allowsEditing = false
picker.sourceType = UIImagePickerControllerSourceType.camera
picker.cameraCaptureMode = .photo
picker.modalPresentationStyle = .fullScreen
present(picker,animated: true,completion: nil)
}
else
{
noCamera()
}
}
private func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let image: UIImage = info[UIImagePickerControllerOriginalImage] as! UIImage;
myImageView.contentMode = .scaleToFill
myImageView.image = image
self.dismiss(animated:true, completion: nil)
}
I must confess I do not know what version of swift I'm using. I'm assuming the latest because I just updated the MacBook Pro until it couldn't do any more. I'm using Xcode 8.2.1 and I'm testing this on a IPhone with IOS 10.2.1 I think it's a IPhone 7s.
Any help is appreciated
Edit:
I'm setting that in this function if that is the wrong place I will move it I just cannot figure out to where. ?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view
picker.delegate = self
}
I'm made aware that this might be a duplicate of another question however when I click to that one they are handling the photo library.
I'm trying to handle the camera and I'm having a issue with returning the image to my imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])...
what they talk about doesn't seem to be working for me and they are using things that I've been told is depricated.
edit 2:
this is how I initialise the picker object as well as how the class is defined
class ViewController: UIViewController,UINavigationControllerDelegate,UIImagePickerControllerDelegate {
let picker = UIImagePickerController()
#IBOutlet weak var myImageView: UIImageView!
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
myImageView.image = image
} else if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
myImageView.image = image
}
myImageView.contentMode = .scaleToFill
self.dismiss(animated:true, completion: nil)
}
I am using UIImagePickerController to allow the user to take a picture. I want to allow him/her to edit it afterwards but, whatever I do, I get nothing.
Here is my code (I am using Xamarin):
UIImagePickerController imagePicker = new UIImagePickerController ();
// set our source to the camera
imagePicker.SourceType = UIImagePickerControllerSourceType.Camera;
// set what media types
//imagePicker.MediaTypes = UIImagePickerController.AvailableMediaTypes (UIImagePickerControllerSourceType.Camera);
// show the camera controls
imagePicker.ModalPresentationStyle = UIModalPresentationStyle.CurrentContext;
imagePicker.ShowsCameraControls = true;
imagePicker.AllowsEditing = true;
imagePicker.SetEditing (true,true);
imagePicker.PreferredContentSize = new SizeF(900,600);
imagePicker.CameraCaptureMode = UIImagePickerControllerCameraCaptureMode.Photo;
imagePicker.Title="taste.eat. image";
// attach the delegate
imagePicker.Delegate = new ImagePickerDelegate();
// show the picker
NavigationController.PresentViewController(imagePicker, true,null);
Am I missing something?
EDIT:
I have followed the tutorial and I am getting to the screen with the rectangle, but if i pan or zoom it just snaps back to the center once I lift my finger. Is it possible to get to this screen from the photos application?
When using UIImagePickerController's delegate
method - imagePickerController:didFinishPickingMediaWithInfo:, we get the image using
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
This code will always return the original image, even if editing is ON.
Try using
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
This will return the edited image if editing is ON.
Hope this helps.
The AllowsEditing property simply allows the user to crop to a square if picking an image and trim the video if picking a video.
Any other functionality needs to be implemented with custom UI and code.
See this question:iPhone SDK - How to customize the crop rect in UIImagePickerController with allowsEditing on?
What you are showing in the screenshot is not part of UIImagePickerController, unfortunately
SWIFT 3
I was having a hard time returning the cropped image (simple mistake on my end). Instead of using UIImagePickerControllerOriginalImage, you need UIImagePickerControllerEditedImage. See below:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// The info dictionary contains multiple representations of the image, and this uses the cropped image.
let selectedImage = info[UIImagePickerControllerEditedImage] as! UIImage
// Set yourImageView to display the selected image.
yourImage.image = selectedImage
// Dismiss the picker.
dismiss(animated: true, completion: nil)
}
SWIFT 4+
There have been some changes after Swift 4. UIImagePickerControllerEditedImage changed to UIImagePickerController.InfoKey.editedImage.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let selectedImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage
imageView.image = selectedImage
dismiss(animated: true, completion: nil)
}
It will be work like this way.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let selectedImage = info[UIImagePickerControllerEditedImage] as! UIImage
userPhoto.image = selectedImage
dismiss(animated: true, completion: nil)
}
There is no way to enable filters by just changing property like allowsEditing = YES. It will only display a cropping tool. As per your screenshot it's look like you have integrated some buggy open source library and without looking at the source code it would be difficult to fix your center cropping bug.
Better to post some concrete detail about your implementation or switch to standard open source library.