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)
}
Related
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)
}
}
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 {
Im trying to make a pick selecter but I get Use unresolved identifier 'imageusr' . I tried changing the Target Membership and with that I get a lot more errors. imageusr.image = image ( here its where it shows the error )
Import UIkit class ViewController2: UIViewController {
#IBOutlet weak var imageusr: UIImageView!
var imagepick = UIImagePickerController()
#IBAction func seleccionar(_ sender: Any) {
imagepick.sourceType = .photoLibrary
imagepick.allowsEditing = true
present(imagepick, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
imageusr.roundedImage()
imagepick.delegate = (self as! UIImagePickerControllerDelegate & UINavigationControllerDelegate)
// Do any additional setup after loading the view.
} here
enter extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
imageusr.image = image
}
dismiss(animated: true, completion: nil)
}
}
Looks like it's a code alignment issue, the extension should be declared outside of the class
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var imageusr: UIImageView!
var imagepick = UIImagePickerController()
#IBAction func seleccionar(_ sender: Any) {
imagepick.sourceType = .photoLibrary
imagepick.allowsEditing = true
present(imagepick, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
imageusr.roundedImage()
imagepick.delegate = self
// Do any additional setup after loading the view.
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
imageusr.image = image
}
dismiss(animated: true, completion: nil)
}
}
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 :
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!