Swift 2: Image picker crashes after at didFinishPickingMediaWithInfo - ios

I am creating an app that utilises this image picker code retrieved from: https://github.com/projectwakii/UIImagePickerController-in-Swift
Shown below:
#IBAction func imageButtonDidPress(sender: AnyObject) {
print("pressed")
//show the action sheet (i.e. the little pop-up box from the bottom that allows you to choose whether you want to pick a photo from the photo library or from your camera
let optionMenu = UIAlertController(title: nil, message: "Where would you like the image from?", preferredStyle: UIAlertControllerStyle.ActionSheet)
let photoLibraryOption = UIAlertAction(title: "Photo Library", style: UIAlertActionStyle.Default, handler: { (alert: UIAlertAction!) -> Void in
print("from library")
//shows the photo library
self.imagePicker.allowsEditing = true
self.imagePicker.sourceType = .PhotoLibrary
self.imagePicker.modalPresentationStyle = .Popover
self.presentViewController(self.imagePicker, animated: true, completion: nil)
})
let cameraOption = UIAlertAction(title: "Take a photo", style: UIAlertActionStyle.Default, handler: { (alert: UIAlertAction!) -> Void in
print("take a photo")
//shows the camera
self.imagePicker.allowsEditing = true
self.imagePicker.sourceType = .Camera
self.imagePicker.modalPresentationStyle = .Popover
self.presentViewController(self.imagePicker, animated: true, completion: nil)
})
let cancelOption = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: {
(alert: UIAlertAction!) -> Void in
print("Cancel")
self.dismissViewControllerAnimated(true, completion: nil)
})
//Adding the actions to the action sheet. Camera will only show up as an option if the camera is available in the first place.
optionMenu.addAction(photoLibraryOption)
optionMenu.addAction(cancelOption)
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) == true {
optionMenu.addAction(cameraOption)} else {
print ("I don't have a camera.")
}
self.presentViewController(optionMenu, animated: true, completion: nil)
/*
just adding extra text for fun
*/
}
// MARK: - Image Picker Delegates
//The UIImagePickerController is a view controller that gets presented modally. When we select or cancel the picker, it runs the delegate, where we handle the case and dismiss the modal.
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
print("finished picking image")
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
//handle media here i.e. do stuff with photo
print("imagePickerController called")
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
imageButtonImage.image = chosenImage
dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
//what happens when you cancel
//which, in our case, is just to get rid of the photo picker which pops up
dismissViewControllerAnimated(true, completion: nil)
}
The issue is that most of the times that I select an image the app crashes.I think it is partially due to some sort of low memory warning, although I am not sure. It is after I click the "use photo" button as shown below
Also, does anybody have any idea how I can remove the square thing whenever I take the photo as visible above
Thanks in advance!

Try using:
self.imagePicker.allowsEditing = false

Related

Error while opening Popover Option to choose either Camera or photo Library on iPad in Xcode

I am able to open a Photo Library on an iPhone using the following code:-
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBAction func TapOnImageView(sender: UITapGestureRecognizer) {
//call Alert function
self.showAlert()
}
//Show alert to selected the media source type.
private func showAlert() {
let alert = UIAlertController(title: "Image Selection", message: "From where you want to pick this image?", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(action: UIAlertAction) in
self.getImage(fromSourceType: .camera)
}))
alert.addAction(UIAlertAction(title: "Photo Album", style: .default, handler: {(action: UIAlertAction) in
self.getImage(fromSourceType: .photoLibrary)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .destructive, handler: nil))
self.present(alert, animated: true, completion: nil)
}
//get image from source type
private func getImage(fromSourceType sourceType: UIImagePickerController.SourceType) {
//Check is source type available
if UIImagePickerController.isSourceTypeAvailable(sourceType) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.sourceType = sourceType
self.present(imagePickerController, animated: true, completion: nil)
}
}
//MARK:- UIImagePickerViewDelegate.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
self.dismiss(animated: true) { [weak self] in
guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
//Setting image to your image view
self?.imageView.image = image
self?.imageView.contentMode = .scaleToFill
self?.image = self?.imageView.image
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
But, when I am running my app on iPad, I am getting the following error:-
Thread 1: Exception: "Your application has presented a UIAlertController (<UIAlertController: 0x7ffd07875e00>) of style UIAlertControllerStyleActionSheet from App Name.ViewController (<App_Name.ViewController: 0x7ffd07635620>). The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation."
Could anyone please let me know, what can I do to open camera and Photo Library on iPad in Xcode? Thanks for the help!
Updated:
Solution:
var alertStyle = UIAlertController.Style.actionSheet
if (UIDevice.current.userInterfaceIdiom == .pad) {
alertStyle = UIAlertController.Style.alert
}
let alert = UIAlertController(title: "Image Selection", message: "From where you want to pick this image?", preferredStyle: alertStyle)
You are trying to present an UIAlertController on iPad which requires to set modalStyle to UIModalPresentationPopover and its sourceView and sourceRect. Please see this answer for more details.

When i tap on image button for UIImagePicker galary to pick image in iPad then app is crashing why?

I am using UIImagePicker for picking images, it forks fine for iPhone gallery to pick images. but when i test app in iPad in xcode here when i tap on image button then app is crashing, i dont know why.
here is the code:
#IBAction func addProfileBtnAction(_ sender: Any) {
let actionSheetController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
//Create and add the Cancel action
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) { action -> Void in
//Just dismiss the action sheet
}
actionSheetController.addAction(cancelAction)
//Create and add first option action
let takePictureAction: UIAlertAction = UIAlertAction(title: "TakePhoto", style: .default) { action -> Void in
//Code for launching the camera goes here
self.openCameraPicker()
}
actionSheetController.addAction(takePictureAction)
//Create and add a second option action
let choosePictureAction: UIAlertAction = UIAlertAction(title: "ChooseFromLibrary", style: .default) { action -> Void in
//Code for picking from Gallery goes herece
self.openPhotoGallery()
}
actionSheetController.addAction(choosePictureAction)
//Present the AlertController
self.present(actionSheetController, animated: true, completion: nil)
}
func openCameraPicker() {
picker.sourceType = UIImagePickerController.SourceType.camera
picker.cameraCaptureMode = .photo
picker.modalPresentationStyle = .fullScreen
present(picker,animated: true,completion: nil)
}
func openPhotoGallery() {
picker.sourceType = .photoLibrary
picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
present(picker, animated: true, completion: nil)
}
// MARK: - UIImagePickerControllerDelegate Methods
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
//pickedImage = image
imgPick.image = image
}
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
i have checked the crash point by giving breakpoint, when it comes to openPhotoGallery() then its crashing.
UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in may also be helpful.
please help me with the code. to pic images from iPad gallery as well.
For iPad add your code :
(under the let actionSheetController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) line)
actionSheetController.popoverPresentationController?.sourceView = self.yourView
Hope it helps...

Saving photo to image in Swift 4.2

I am having a problem displaying the photo I just took or chose to the image view.
Below is a pic of the imagview on the left and the licencePhoto button on right.
When I click on Take Photo, it allows me to take a pic or select from my library, as the code shows:
#IBAction func seclectOrTakePhoto(_ sender: Any) {
pickerController.delegate = self
pickerController.allowsEditing = true
let alertController = UIAlertController(title: "Add a Picture", message: "Choose From", preferredStyle: .actionSheet)
let cameraAction = UIAlertAction(title: "Camera", style: .default) { (action) in
self.pickerController.sourceType = .camera
self.present(self.pickerController, animated: true, completion: nil)
}
let photosLibraryAction = UIAlertAction(title: "Photos Library", style: .default) { (action) in
self.pickerController.sourceType = .photoLibrary
self.present(self.pickerController, animated: true, completion: nil)
}
let savedPhotosAction = UIAlertAction(title: "Saved Photos Album", style: .default) { (action) in
self.pickerController.sourceType = .savedPhotosAlbum
self.present(self.pickerController, animated: true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alertController.addAction(cameraAction)
alertController.addAction(photosLibraryAction)
alertController.addAction(savedPhotosAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
But, it does not display the photo to the licensePhoto image and in Firebase, it is uploading the pic I have displayed in the image view as below and not the one I just took with phone.
How can I achieve this?
Edited
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
self.licensePhoto.image = image
self.dismiss(animated: true, completion: nil)
// any time the photo changes, check the button status
updateSignupButtonStatus()
}
After searching and looking through tutorials, I finally got something to work:
#objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
licensePhoto.contentMode = .scaleAspectFit
licensePhoto.image = chosenImage
pickerController.dismiss(animated: true, completion: nil)
}

UIImagePickerController image in Swift

I am using a UIImagePickerController in my program and it is effectively changing the image of an imageview i have added. However, whenever I restart this app and come back to the home screen, it is automatically resetting to the default image I had it to before, rather than the user selected image. How can I make it so that it records which image was last used, and reloads it every time the program starts?
var imagePicker = UIImagePickerController()
func chooseImage(_ sender: Any) { //function called with button press
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.allowsEditing = true
let actionSheet = UIAlertController(title: "Photo Source", message: "Choose a source", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action:UIAlertAction) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePickerController.sourceType = .camera
self.present(imagePickerController, animated: true, completion: nil)
}else{
print("Camera not available")
}
}))
actionSheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action:UIAlertAction) in
imagePickerController.sourceType = .photoLibrary
self.present(imagePickerController, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "Default", style: .default, handler: { (action:UIAlertAction) in
self.avatarImageView.image = UIImage(named: "Avatar.png")
}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerEditedImage] as! UIImage
avatarImageView.image = image
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
Since the app is going out of memory, you'll need some kind of persistence mechanism for saving the image. The simplest way to do this would be to store the image in UserDefaults. This can be accomplished like this:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerEditedImage] as! UIImage
avatarImageView.image = image
UserDefaults.standard.set(UIImagePNGRepresentation(image), forKey: "avatarImage")
picker.dismiss(animated: true, completion: nil)
}
Then when you reopen the app you'll need to check whether you've previously saved an avatarImage in UserDefaults and load it from there:
// Could be in viewDidLoad or wherever else you load your image
override func viewDidLoad() {
if let imageData = UserDefaults.standard.object(forKey: "avatarImage") as? Data {
avatarImageView.image = UIImage(data: imageData)
}
}

Include UIImagePickerController in a view

I need to make a view that works like pages, with a popup in which I can choose to pick a photo from my library or create a new one.
Currently, I have a ViewController, present as Popover. In the ViewController, I inserted a ContainerView and I declared that its class is UIImageViewController. This is showing me the photo library but I don't find how to pick anything in : My ViewController presented as Popover.
When I choose a photo, nothing's happening. I've tried to put some functions
(func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!))
in my ViewController but it does not work. I've read that UIImagePickerController does not support subclassing, so how Pages do this stuff ?
Here is my ViewController code :
import UIKit
class MenuAddResources: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var newMedia: Bool?
let imagePicker = UIImagePickerController()
#IBAction func takePhoto(sender: AnyObject) {
if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
//load the camera interface
let picker : UIImagePickerController = UIImagePickerController()
picker.sourceType = UIImagePickerControllerSourceType.Camera
picker.delegate = self
picker.allowsEditing = false
self.presentViewController(picker, animated: true, completion: nil)
self.newMedia = true
}
else{
//no camera available
let alert = UIAlertController(title: NSLocalizedString("ERROR", comment: ""), message: NSLocalizedString("NO_CAMERA", comment: ""), preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Default, handler: {(alertAction)in
alert.dismissViewControllerAnimated(true, completion: nil)
}))
self.presentViewController(alert, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func image(image: UIImage, didFinishSavingWithError error: NSErrorPointer, contextInfo:UnsafePointer<Void>) {
if error != nil {
let alert = UIAlertController(title: NSLocalizedString("ERROR", comment: ""), message: NSLocalizedString("IMAGE_SAVE_FAILED", comment: ""), preferredStyle: UIAlertControllerStyle.Alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Cancel, handler: nil)
alert.addAction(cancelAction)
self.presentViewController(alert, animated: true, completion: nil)
}
}
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!){
self.dismissViewControllerAnimated(true, completion: { () -> Void in
})
// Let's store the image
let now:Int = Int(NSDate().timeIntervalSince1970)
let imageData = UIImageJPEGRepresentation(image, 85)
//imageData?.writeToFile(documentsDirectory + "/\(now).jpg", atomically: true)
print(imageData)
/* will do stuff with the image */
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
It appears you are using UIImagePickerViewController through a
container view and therefore the delegate isnt set , thus no callbacks
to receiving the image picked methods.
To fix this, you must override prepareForSegue in your class
and in that cast the segue.destinationViewController to your picker and set its delegate to self

Resources