1

I am making a custom camera in Swift. I declared it global like this:

let image = UIImagePickerController()

I have made OverlayVC (UIViewController) in IB. Made a shutter button and hooked it up like this:

@IBAction func shutterTapped(_ sender: Any) {
    print("shutterTapped")
    image.takePicture()
}

I instantiate this overlay before presenting:

image.delegate = self
image.sourceType = .camera
image.cameraDevice = .front
image.allowsEditing = false
let overlay = self.storyboard?.instantiateViewController(withIdentifier: "OverlayVC")
image.cameraOverlayView = overlay?.view
image.showsCameraControls = false
self.present(image, animated: true, completion: nil)

Now when I run the build on device and tap on the shutter button, I can visually see it being tapped (fade out/in) but the code in shutterTapped() never executes.

Kashif
  • 4,642
  • 7
  • 44
  • 97
  • simplest question: have you tried to reconnect IBAction? – Miknash Mar 29 '18 at 17:45
  • @Miknash Just tried and it did not help. – Kashif Mar 29 '18 at 17:52
  • I think that your action needs to be connected with controller "OverlayVC" and then via delegate notice controller from which you are calling take picture. Simply connect IBAction with OverlayVC and check if that one is called. If that works I will write down the code needed for propagation of the event to the calling view controller – Miknash Mar 29 '18 at 17:58
  • @Miknash But I am not even able to print to log from this IBAction let alone post a notification to other VC. – Kashif Mar 29 '18 at 18:01
  • is shutterTapped in the OverlayVC or in the view controller calling UIImagePickerController? – Miknash Mar 29 '18 at 18:04
  • @Miknash shutterTapped is in OverlayVC – Kashif Mar 29 '18 at 18:04
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/167835/discussion-between-kashif-and-miknash). – Kashif Mar 29 '18 at 18:43
  • It's the best if you can give us a debug repo. If you can't, please update your question with image from storyboard for shutter button – trungduc Mar 30 '18 at 04:17

1 Answers1

3

Why is it not really working?

Adding view of the view controller removes controller itself and no one can actually get the event. So, you get the view but not events. and to support this:

enter image description here

Solution that will actually work with your code would be:

image.cameraOverlayView = overlay?.view
if let viewController  = overlay {

    for view in viewController.view.subviews {
        if let button = view as? UIButton {
           button.addTarget(self, action: #selector(self.takePicture), for: UIControlEvents.touchDown)
        }
    }
}

You can also add tag to it so you can check which button is which if you have more of them.

Alternate Solution:

Create UIView subclass and xib for it. Same view you had in the OverlayVC. Then, when adding overlay use following:

image.sourceType = .camera
image.cameraDevice = .front
image.allowsEditing = false
let myOverlay = Bundle.main.loadNibNamed("CameraOverlay", owner: self, options: nil)
image.cameraOverlayView = myOverlay?.first as! UIView
image.showsCameraControls = false
self.present(image, animated: true, completion: nil)

Note that force unwrap should be protected with either guard or if let when casting to UIView.

Miknash
  • 7,888
  • 3
  • 34
  • 46