didFinishPickingImage does not get triggered - ios

I have a class
class ActivitiesMainPageController: UICollectionViewController ,UIImagePickerControllerDelegate, UINavigationControllerDelegate{
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
switch indexPath.item {
case 0 :
let takePictureInstance = takePictures()
takePictureInstance.presentCamera()
}
}
The takePictures() is s custom class
class takePictures: UIViewController, UIImagePickerControllerDelegate, UIAlertViewDelegate, UINavigationControllerDelegate
{
var imagePicker: UIImagePickerController! = UIImagePickerController()
func presentCamera()
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)
{
let objViewController = UIApplication.shared.keyWindow?.rootViewController
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = false
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
objViewController?.present(imagePicker,animated: true,completion: nil)
}
else
{
// error msg
print ("error displaying Camera")
noCamera()
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
print(self.Tag + "image picker controller")
self.dismiss(animated: true, completion: nil)
}
}
The didfinishpickingimage never gets triggered. I don't see the print statement. After reading the SO here, I think I am not doing the delegate correctly. Can you please help?

The problem is in your ActivitiesMainPageController class. It's a memory management issue. You create a local instance of your takePictures class (FYI - class names should start with uppercase letters), and then call the presentCamera method. And then the takePictureInstance variable immediately goes out of scope. This means it has no more references and it gets deallocated.
So at this point, the image picker's (weak) delegate becomes nil. This is why the image picker delegate method is never called.
There are two ways to fix this:
Keep a strong reference to the takePictures instance inside your ActivitiesMainPageController class (use a property instead of a local variable). But this has the problem of not knowing when to release the instance.
Perform a little trick inside the takePictures class where it keeps a strong reference to itself when created, and then releases that strong reference after the image picker is dismissed.
Option 2 can be implemented like this:
class takePictures: UIViewController, UIImagePickerControllerDelegate, UIAlertViewDelegate, UINavigationControllerDelegate
{
var strongSelf: takePictures?
var imagePicker: UIImagePickerController! = UIImagePickerController()
func presentCamera()
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)
{
let objViewController = UIApplication.shared.keyWindow?.rootViewController
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = false
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
objViewController?.present(imagePicker,animated: true,completion: nil)
strongSelf = self // keep me around
}
else
{
// error msg
print ("error displaying Camera")
noCamera()
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
print(self.Tag + "image picker controller")
self.dismiss(animated: true, completion: nil)
strongSelf = nil // let me go
}
}

Why are you presenting the UIImagePicker from the takePictures class (Should be TakePictures)? I think the problem is originating because the view controller you're currently in is not the one presenting the picker. If you pulled that presentCamera() function out and put it in the ActivitiesMainPageControllerand assigned <- that as the delegate and also switched the method signature to the correct one:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
You should have better luck.

Related

WKWebView ImagePicker catch event of choosing of picture iOS

I'm working with WKWebView on which I'm tapping 'Load file'. WKWebView opening for me UIImagePickerView during which I need to know - what image was choosen.
Worked for me.
override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
if let imagePicker = viewControllerToPresent as? UIImagePickerController {
previousIPDelegate = imagePicker.delegate
imagePickerController = imagePicker
imagePickerController?.delegate = self
}
super.present(viewControllerToPresent, animated: flag, completion: completion)
}
After this - you'll be able to work with didFinishPickingMediaWithInfo func where you can catch and work with chosen media, should return old delegate to imagePicker and call didFinishPickingMediaWithInfo func in old delegate
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var newInfo = info
if let pickedImage = newInfo[UIImagePickerControllerOriginalImage] as? UIImage {
/// DO YOUR STUFF HERE
}
picker.delegate = previousIPDelegate
previousIPDelegate?.imagePickerController!(picker, didFinishPickingMediaWithInfo: newInfo)
}
You should do the same in DidCancel func
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.delegate = previousIPDelegate
previousIPDelegate?.imagePickerControllerDidCancel!(picker)
}

How to use UIImagePickerController with delegate?

I added UIView (A Class) as a xib instance to ViewController.
I want to get image from UIImagePickerController of ViewController class by action (in A Class) and return it to A Class.
I wrote up the following codes.
However, I do not know how to return to A Class.
I made delegate to ViewController again but I abandoned it because I displayed various errors of delegate. [Un wrap error ..., just did not move anything ... etc].
// A Class
class A: CustomDelegate{
var delegate001: PhotoLibraryDelegate!
class func instance() -> A {
return UINib(nibName: "A", bundle: nil).instantiate(withOwner: self, options: nil)[0] as! A
}
#IBAction func openPhotoLibrary(_ sender: Any) {
self.delegate001.selectPhoto() //I want photo in A Class XD. so make Delegate!!
}
}
#objc protocol PhotoLibraryDelegate {
func selectPhoto()
}
//ViewController Class
class ViewController: PhotoLibraryDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate{
let a = A.instance()
override func viewDidLoad() {
super.viewDidLoad()
a.delegate006 = self
}
func selectPhoto() {
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
let pickerView = UIImagePickerController()
pickerView.sourceType = .photoLibrary
pickerView.delegate = self
self.present(pickerView, animated: true)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as? UIImage // Yeah, I selected the image!!
self.dismiss(animated: true)
//... Wa!? I want to return "image" to A class. OMG.
}
}
The simplest way is that you have already created the instance of A class. Now just directly assign the image to it.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as? UIImage // Yeah, I selected the image!!
a.imageView.image = image
self.dismiss(animated: true)
}

Why "picker.delegate = self necessary"?

I am creating a simple camera app.
In the code, UIImagePickerControllerclass is the delegate of ViewControllerClass instance.
But why "picker.delegate = self"is necessary in this code?
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBAction func launchCamera(_ sender: UIBarButtonItem) {
let camera = UIImagePickerControllerSourceType.camera
if UIImagePickerController.isSourceTypeAvailable(camera) {
let picker = UIImagePickerController()
picker.sourceType = camera
picker.delegate = self
self.present(picker, animated: true)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
self.imageView.image = image
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
self.dismiss(animated: true)
}
delegate of UIImagePickerController includes UIImagePickerControllerDelegate and UINavigationControllerDelegate.
UIImagePickerControllerDelegate for catch users' action about take photo or choose picture.
UINavigationControllerDelegate for view controller navigation between album and photo

Why doesn't UIImagePickerController delegate to my Object class?

class CameraPicker: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var viewController:MyProfileVC!
func launchCamera() {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
let imagePicker:UIImagePickerController = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
imagePicker.cameraDevice = UIImagePickerControllerCameraDevice.front
imagePicker.cameraCaptureMode = .photo
imagePicker.allowsEditing = false
self.viewController.present(imagePicker, animated: true, completion: nil)
} }
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("didFinishPickingMedia")
}
This is my object class function, but 'didFinishPickingMediaWithInfo' function doesn't get called after taking the picture. Also, the viewcontroller which is presenting the imagepicker is a different Swift file
I had the same problem and I've found a solution, so I'm posting my version (I'm taking a picture from the photo library but it's the same :) ).
I had a memory management issue.
I've created an IBAction function where I instantiated my camera handler class (with the delegate inside...). At the end of the function the variable goes out of scope and it's deallocated. To solve the issue I've made it as instance variable.
That's my code for the VC with my UiButton:
class STECreateUserVC: UIViewController {
#IBOutlet weak var imgAvatar: UIImageView!
let cameraHandler = STECameraHandler()
#IBAction func buttonPressed(_ sender: UIButton) {
cameraHandler.importPictureIn(self) { [weak self] (image) in
self?.imgAvatar.image = image
}
}
}
...and that's my handler:
class STECameraHandler: NSObject {
let imagePickerController = UIImagePickerController()
var completitionClosure: ((UIImage) -> Void)?
func importPictureIn(_ viewController: UIViewController, completitionHandler:((UIImage) -> Void)?) {
completitionClosure = completitionHandler
imagePickerController.delegate = self
imagePickerController.allowsEditing = true
imagePickerController.sourceType = .photoLibrary
imagePickerController.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
viewController.present(imagePickerController, animated: true, completion: nil)
}
}
extension STECameraHandler: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let completitionClosure = completitionClosure, let image = info[UIImagePickerControllerEditedImage] as? UIImage {
completitionClosure(image)
}
imagePickerController.dismiss(animated: true)
}
}
I've used a closure in order to have a cleaner code.
This:
self.viewController.present(imagePicker, animated: true, completion: nil)
should be:
self.present(imagePicker, animated: true, completion: nil)

Add a circular cropping component for UIImagePicker?

I Have a circular framed UIImageView and I need to add a circular framed cropping tool for the UIImagePickerController, after the image is selected from a photo library. Very similar to Instagram's UIImagePicker's crop component. How do I add this type of component?
UPDATE
I've found this repo with a circular cropping tool https://github.com/ruslanskorb/RSKImageCropper
but can someone guide me on to how to implement this cropping tool with the UIImagePickerController after the user selects a photo from the photo library?
UPDATE
I am getting the following message in my debugger :
and the buttons in my crop view are disabled, meaning I cannot select them.. what message is the debugger relaying on to me?
here is my code:
#IBAction func chooseProfilePicture(sender: AnyObject) {
var myPickerController = UIImagePickerController()
myPickerController = UIImagePickerController()
myPickerController.delegate = self;
myPickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(myPickerController, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
var image : UIImage = (info[UIImagePickerControllerOriginalImage] as? UIImage)!
editProfilePictureImageView.image = image
self.dismissViewControllerAnimated(false, completion: { () -> Void in
var imageCropVC : RSKImageCropViewController!
imageCropVC = RSKImageCropViewController(image: image, cropMode: RSKImageCropMode.Circle)
imageCropVC.delegate = self
self.navigationController?.pushViewController(imageCropVC, animated: true)
})
}
Example Demo
Yes you can add RSKImageCropper in your UIImagePickerController
define imagePicker
var imagePicker : UIImagePickerController!
in ViewDidLoad
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
self.presentViewController(imagePicker, animated: true, completion: nil)
Delegate methode :
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject])
{
var image : UIImage = (info[UIImagePickerControllerOriginalImage] as? UIImage)!
picker.dismissViewControllerAnimated(false, completion: { () -> Void in
var imageCropVC : RSKImageCropViewController!
imageCropVC = RSKImageCropViewController(image: image, cropMode: RSKImageCropMode.Circle)
imageCropVC.delegate =self
self.navigationController?.pushViewController(imageCropVC, animated: true)
})
}
see :
Kirit Modi's answer was exactly what I needed, although I needed to do one thing to make this work. For those that dont download the test project, make sure to implement your delegate methods:
Swift 3:
extension YourViewControllerClass: RSKImageCropViewControllerDelegate {
func imageCropViewControllerDidCancelCrop(_ controller: RSKImageCropViewController) {
_ = self.navigationController?.popViewController(animated: true)
}
func imageCropViewController(_ controller: RSKImageCropViewController, didCropImage croppedImage: UIImage, usingCropRect cropRect: CGRect) {
self.avatarImageView.image = croppedImage
_ = self.navigationController?.popViewController(animated: true)
}
}
Swift 2:
extension YourViewControllerClass: RSKImageCropViewControllerDelegate {
func imageCropViewControllerDidCancelCrop(controller: RSKImageCropViewController) {
self.navigationController?.popViewControllerAnimated(true)
}
func imageCropViewController(controller: RSKImageCropViewController, didCropImage croppedImage: UIImage, usingCropRect cropRect: CGRect) {
self.avatarImageView.image = croppedImage
self.navigationController?.popViewControllerAnimated(true)
}
}
For Swift 2.2:
add delegate methods to your class:
class ViewController: UIViewController, UIImagePickerControllerDelegate, RSKImageCropViewControllerDelegate, UINavigationControllerDelegate
define imagePicker
var imagePicker : UIImagePickerController!
in viewDidLoad()
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(imagePicker, animated: true, completion: nil)
And delegate methode :
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
let image : UIImage = image
picker.dismissViewControllerAnimated(false, completion: { () -> Void in
var imageCropVC : RSKImageCropViewController!
imageCropVC = RSKImageCropViewController(image: image, cropMode: RSKImageCropMode.Circle)
imageCropVC.delegate = self
self.navigationController?.pushViewController(imageCropVC, animated: true)
})
}
Of course it need to do bridge for objective C class
Oh, link to RSKImageCrop

Resources