Passing class via delegate : property not updated - swift

don't understand why I didn't get my class property updated (imageData property).
simple example, 2 view controllers embed in navigation controller (important for me):
first one : ViewController with an imageView and a button to the second view controller (via segue)
class ViewController: UIViewController, choosePicVCDelegate {
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.imageView.clipsToBounds = true
}
func goodPic(vc: choosePicViewController) {
if let data = vc.imageData {
let image = UIImage(data: data)
self.imageView.image = image
}
vc.navigationController?.popViewControllerAnimated(true)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let vc = segue.destinationViewController as! choosePicViewController
vc.delegate = self
}
}
second one : choosePicViewController with an imagePicker to choose the image to display in the first ViewController. 2 buttons: one to choose the image, the other to go back to the first view controller with the delegate..
protocol choosePicVCDelegate {
func goodPic(vc: choosePicViewController)
}
class choosePicViewController: UIViewController {
var delegate: choosePicVCDelegate?
let imagePicker = UIImagePickerController()
var imageData: NSData?
#IBAction func back(sender: UIButton) {
delegate?.goodPic(self)
}
#IBAction func coverPick(sender: UIButton) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
imagePicker.allowsEditing = false
self.presentViewController(imagePicker, animated: true, completion: nil)
}
}
}
extension choosePicViewController: UIImagePickerControllerDelegate {
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
self.imageData = UIImageJPEGRepresentation(image, 1.0)
dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
dismissViewControllerAnimated(true, completion: nil)
}
}
always got nil from imageData property, don't understand why.

I think the problem is your extension, i didn't understand why use extension in this case, whatever. Try do it.
You need set delegate from imagePicker.delegate = self, because with this you can listener the UIImagePickerController delegate. I believe with this you resolve.
protocol choosePicVCDelegate {
func goodPic(vc: choosePicViewController)
}
class choosePicViewController: UIViewController, UIImagePickerControllerDelegate {
var delegate: choosePicVCDelegate?
let imagePicker = UIImagePickerController()
var imageData: NSData?
override func viewWillAppear(animated: Bool) {
imagePicker.delegate = self;
}
override func viewDidDisappear(animated: Bool) {
imagePicker.delegate = nil;
}
#IBAction func back(sender: UIButton) {
delegate?.goodPic(self)
}
#IBAction func coverPick(sender: UIButton) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
imagePicker.allowsEditing = false
self.presentViewController(imagePicker, animated: true, completion: nil)
}
}
//Delegates from UIImagePickerControllerDelegate
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
if let img = info[UIImagePickerControllerOriginalImage] as? UIImage{
self.imageData = UIImageJPEGRepresentation(img, 1.0)
delegate?.goodPic(self)
dismissViewControllerAnimated(true, completion: nil)
}
}
}
Hope help you!

Related

How to add 2 or more images into email from photo gallery to MFMailComposeViewController [duplicate]

I am making an app in which there are two UIImageViews. In each image view the user needs to be able to input a different image. Here is the code I have so far.
var imagePicker = UIImagePickerController()
#IBAction func chooseImage1(sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum){
println("Button capture")
imagePicker.delegate = self
imagePicker.sourceType = .SavedPhotosAlbum
imagePicker.allowsEditing = false
self.presentViewController(imagePicker, animated: true, completion: nil)
}
}
#IBAction func chooseImage2(sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum){
println("Button capture")
imagePicker2.delegate = self
imagePicker2.sourceType = .SavedPhotosAlbum
imagePicker2.allowsEditing = false
self.presentViewController(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
chooseImage1.image = pickedImage
let pickedImage2 = info[UIImagePickerControllerOriginalImage] as? UIImage
chooseImage2.image = pickedImage2
dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
dismissViewControllerAnimated(true, completion: nil)
}
This ends up picking the same image for each different image view. I would like to be able to choose two individual photos, one for each view. Thank you for your help.
You only need one UIImagePickerController. You can keep a reference of the tapped view and when the user finish picking the image, you just need to cast the selected view as UIImageView and set its image property:
update: Xcode 11.5 • Swift 5.2 or later
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate ,UINavigationControllerDelegate {
#IBOutlet weak var imageView1: UIImageView!
#IBOutlet weak var imageView2: UIImageView!
var imagePicker = UIImagePickerController()
var selectedVew: UIView!
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
imagePicker.sourceType = .savedPhotosAlbum
imagePicker.allowsEditing = false
[imageView1,imageView2].forEach {
$0?.isUserInteractionEnabled = true
$0?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(chooseImage)))
}
}
#objc func chooseImage(_ gesture: UITapGestureRecognizer) {
if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum) {
selectedVew = gesture.view
present(imagePicker, animated: true)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
(selectedVew as? UIImageView)?.image = info[.originalImage] as? UIImage
dismiss(animated: true)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true)
}
}

Swift 5 UIImagePickerController is not getting called

I have the most standard/out of the box code for calling the delegate function in UIImagePicker:
import Foundation
import UIKit
//import UIKit.UIImage
class FirstViewController:
UIViewController
, UIImagePickerControllerDelegate
{
let imagePicker = UIImagePickerController()
#IBOutlet weak var bigImageView: UIImageView!
var newlyPickedImage: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = Color.offWhiteLight
let singleTap = UITapGestureRecognizer(target: self, action: #selector(onTapImageView))
self.view.isUserInteractionEnabled = true
self.view.addGestureRecognizer(singleTap)
}
#objc func onTapImageView(){
DispatchQueue.main.async {
self.imagePicker.allowsEditing = true
self.imagePicker.sourceType = .photoLibrary
self.present(self.imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(
_ picker: UIImagePickerController
, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any])
{
print("assert enter function") /// not entered
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
self.bigImageView.image = pickedImage
print("picked image: \(pickedImage)")
}
dismiss(animated: true, completion: nil)
}
}
The issue is that func imagePickerController is not getting called. This is odd because in a different view the exact code does call func imagePickerController. I have also tried instantiating a global UIImagePickerController instance in the Appdelegate and referencing that, the call is still not called.
You seem to be missing setting delegate for the UIImagePickerController. Replace your onTapImageView with this:
#objc func onTapImageView(){
DispatchQueue.main.async {
self.imagePicker.allowsEditing = true
self.imagePicker.sourceType = .photoLibrary
self.imagePicker.delegate = self
self.present(self.imagePicker, animated: true, completion: nil)
}
}
Also you need the controller to confirm to UINavigationControllerDelegate so add conformance to FirstViewController like this:
class FirstViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

Use UIImagePicker to set the image in a UIImageView

This is how my code currently looks like. What I expect to happen is the profileImage (UIImageView) to display the selected image as currently it is not happening.
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet var profileImage: UIImageView!
let picker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
picker.sourceType = .photoLibrary
}
#IBAction func photoUploadPressed(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
let myPickerController = UIImagePickerController()
myPickerController.delegate = self;
myPickerController.sourceType = .photoLibrary
self.present(myPickerController, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
selectedImage = image
profileImage.image = image
}
dismiss(animated: true, completion: nil)
}
}
Currently the Image Picker comes up, but once selected it does not change the UIImageView's image.
Any help will be much appreciated.
It is working as expected only error in your code is that you have } missing in photoUploadPressed(_ sender: Any) and you have not declared selectedImage & using it inside imagePickerController
Working code
import UIKit
class ViewController: UIViewController , UIImagePickerControllerDelegate, UINavigationControllerDelegate{
let picker = UIImagePickerController()
var selectedImage: UIImage?
#IBOutlet weak var profileImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
picker.delegate = self
picker.sourceType = .photoLibrary
}
#IBAction func potoUploadPressed(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
let myPickerController = UIImagePickerController()
myPickerController.delegate = self;
myPickerController.sourceType = .photoLibrary
self.present(myPickerController, animated: true, completion: nil)
}// It is missing in your code
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
selectedImage = image // You have not declared selectedImage
profileImage.image = image
}
dismiss(animated: true, completion: nil)
}
}

Memory leaks when using UIImagePickerController in camera mode

This is a simple single view, single ViewController test app. This app has one button in the ViewController. Accessing the PhotoLibrary does not show any leaks, but the camera shows some leaks when presented and more when dismissed.
Here is code:
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let pickerCntrl = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
pickerCntrl.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func takePic(_ sender: Any) {
pickerCntrl.sourceType = UIImagePickerControllerSourceType.camera
pickerCntrl.cameraCaptureMode = .photo
pickerCntrl.allowsEditing = true
if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)){
self.present(pickerCntrl, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// let editedCapture = info[UIImagePickerControllerEditedImage] as! UIImage?
// let origCapture = info[UIImagePickerControllerOriginalImage] as! UIImage?
self.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.dismiss(animated: true, completion: nil)
}
}
ScreenShot :

Segue from a UICollectionReusableView to ImagePicker

I have a class for my UICollectionReusableView, but I need a button in that view to perform a segue from the UICollectionView to an imagePicker. I have tried to use a delegate, but I keep on getting nil for the delegate.
protocol ShouldSegueToImagePickerDelegate{
func shouldSegue()
}
class ProfileHeaderCollectionReusableView: UICollectionReusableView{
var delegate: ShouldSegueToImagePickerDelegate!
#IBAction func pressedChangeBGPicButton(sender: AnyObject) {
delegate.shouldSegue()
}
class ProfileCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, ShouldSegueToImagePickerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate{
var imagePicker = UIImagePickerController()
func shouldSegue() {
imagePicker.allowsEditing = false
imagePicker.sourceType = .PhotoLibrary
self.presentViewController(imagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
imagePicker.dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
imagePicker.dismissViewControllerAnimated(true, completion: nil)
}