UIImagePickerController: Detecting Camera button (shutter) pressed - iphone

I would like to call a method that takes an NSNotification immediately after the user presses the camera shutter (i.e when the "Preview" tab bar has the buttons "Retake" and "Use").
I can't use the didFinishPickingImage method because at this time the user has already pressed the "Use" button.
I have already implemented this by cameraOverlayView property of UIImagePickerController(see comments), but I wonder whether there are quicker ways of 'observing' this action.
Any ideas?

To learn about camera button press event, you can fire a NSNotification for it.
// Add observer for when camera button is pressed
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(yourFunctionToPerform), name: "_UIImagePickerControllerUserDidCaptureItem", object: nil)
Also add the following method to the ViewController where you are creating ImagePickerViewController:
-(void) yourFunctionToPerform{
//Do what you want to do on Camera button tap event
}
I was searching for this problem too, the key/name for the event is really obscure.

You CAN display it AFTER they choose the image.
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingImage:(UIImage *)image
editingInfo:(NSDictionary *)editingInfo
{
//Display the UIAlertView
[alertView show];
//Just never use the image
}
If you don't want to use the image you really don't have to

Related

Image Picker Controller

I am using the UIImagePickerController to take a picture, that works great, but do not want to use the stand image editor, instead I want to use my own custom image editor. I want to transition to that after I take the picture. I am using the method below to push a view controller after the image picker dismisses.
However, I want to push this before the image picker dismiss to avoid an awkward transition. Any ideas?
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info;
The image picker is already in a navigation interface, so you can push anything you like onto the image picker as a secondary (editing) interface:
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage* im = info[UIImagePickerControllerOriginalImage];
if (!im)
return;
SecondViewController* svc =
[[SecondViewController alloc] initWithNibName:nil bundle:nil image:im];
[picker pushViewController:svc animated:YES];
}
You will, however, have to interfere to prevent the image picker from navigating to its own secondary interface. The easy way to do that is to set picker.showsCameraControls = NO and substitute your own controls.
Also, I might be wrong about this, but since you are the navigation controller delegate I think you can just veto an attempt by the image picker to navigate to its own secondary interface. (EDIT: No, I guess not, sorry. The delegate gets a will and a did but not a should message.)

i need to reset the first view with a button press

on an app that i am creating, you need to slide a square through a maze and if it touches the wall, it goes to another screen telling you that you lose. However, when you hit the reset button, it goes back, and the square is in the exact same spot as where it touched the walls. Is there any way that i can press the button and have the square go back to start at the same time? Any feed back is appreciated! Thanks. (By the way, i am using Xcode.)
Here is the code for the button in the .h file:
- (IBAction)retry:(id)sender;
and here is the code for the .m:
- (IBAction)retry:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
Use viewWillAppear to reset your views
-(void) viewWillAppear: (BOOL) animated {
}
Call your initial method on buttonPressEvent.
- (IBAction)retry:(id)sender {
[self viewDidLoad];
}

How can I hide the picture preview?

I am new in iPhone development,
I have built new app to take a picture using UIImagePickerController.
Everything is work fine with me, but I need to dismiss the picture preview that appear after I press the capture button.
I search through the net then I found I must use the following routine.
(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo
{
[self dismissModalViewControllerAnimated:YES];
}
but it didn't work.
Any help or suggestions, is highly appreciated.
You need to add your own camera overlay view. This view should have a button on to Take a picture.
To add an overlay view, create a view with a background colour of clear, then assign your overlay view to the picker control
self.imagePickerController.showsCameraControls = NO;
self.imagePickerController.cameraOverlayView = myOverlayView;
Then in your overlay view button event you call the following:
[imagePickerController takePicture];
This will then fire the following method on the imagePickerDelegate, and you can save your photo etc in there
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

Hide Shutter in UIImagePickerController

I have designed an iris shutter animation for a camera view in an iPhone app.
Unfortunately, it seems impossible to hide Apple's shutter when the view appears, even if I hide the camera controls and create a custom cameraOverlayView.
I have gotten around this by animating my shutter on top of the normal shutter when the view appears, using the viewWillAppear and viewDidAppear methods of UIImagePickerController. However, I can't get the shutter to be hidden under my shutter the first time through. When the app launches, it shows a camera view, and the original shutter is visible. On all subsequent views of the cameraController, my workaround works. Any suggestions?
Here's my code. This is from my app delegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
cameraController = [[CameraController alloc] initWithMode:#"camera"];
[window addSubview:cameraController.view];
}
And this is from my UIImagePickerController subclass:
- (void) viewWillAppear:(BOOL)animated {
if (self.sourceType != UIImagePickerControllerSourceTypePhotoLibrary || simulatorView) {
[self addShutter];
[shutter close];
}
[super viewWillAppear:animated];
}
- (void) viewDidAppear:(BOOL)animated {
if (self.sourceType != UIImagePickerControllerSourceTypePhotoLibrary || simulatorView) {
[shutter openShutter:.5f];
}
[super viewDidAppear:animated];
}
Note that the docs say that subclassing UIImagePickerController isn't supported, so it may work in some cases but isn't "safe". Not sure if it would get rejected by the app store. (Probably depends on how picky their static code verification tool is.)
I don't really have a good answer, but you might try either 1) iterating over the subviews of the picker's main view to see if you can identify whatever is being used to animate the shutter, then mangle it so that it won't display, or 2) for the initial animation, just show the initial image picker main view under another opaque black view. Not sure if the user-specified overlay view would work for that or not, but you might be able to do those without subclassing.
Searching for undocumented subviews is another thing that's theoretically unsafe though since who knows how the implementation might change in the future.
Possibly too late, but my proposal is to use the following notifications (found while debugging)
PLCameraControllerAvailable - camera controller object is initiated, but shutter is not visible yet
PLCameraViewIrisAnimationDidEndNotification - iris animation is completed.
And the usage is straightforward: call UIGetScreenImage() on 1st notification, render grabbed image on screen (fullscreen) just above the UIImagePicker. Destroy rendered image on the 2nd notification.
I try the same thing with no results, so I do this workaround:
1- Suppose you have a method called showAllButtons with no parameters that will show all your custom things (buttons, tool bars,...)
2- Initialize all the custom controls hidden
3- Write a method that will call the last function but within an interval:
-(void)showAllButtonsDelayed:(NSTimeInterval)a_iMsToDelay
{
NSTimer* tmpShowButtonsTimer = [NSTimer timerWithTimeInterval:a_iMsToDelay target:self selector:#selector(showAllButtons) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:tmpShowButtonsTimer forMode:NSDefaultRunLoopMode];
}
4- Call that method in the willDidAppear method of the UIImagePickerController subclass. Play with some values of a_iMsToDelay.
Hope this helps.

iPhone: taking a picture programmatically

I'm trying to use the UIImagePickerController interface from OS 3.1, with the cameraOverlayView and takePicture, but I've clearly failed to understand how this works, and so I'm not getting the behaviour I want.
What I want to do is open the camera and take a picture automatically without having to having the user interact with the picker or edit the image. So I subclass UIImagePickerController (similar to the example in http://github.com/pmark/Helpful-iPhone-Utilities/tree/master/BTL%20Utilities/) and turn off all of the controls:
- (void)displayModalWithController:(UIViewController*)controller animated:(BOOL)animated {
self.sourceType = UIImagePickerControllerSourceTypeCamera;
self.showsCameraControls = NO;
self.navigationBarHidden = YES;
self.toolbarHidden = YES;
// Setting the overlay view up programmatically.
ipView = [[ImagePickerView alloc] init];
self.cameraOverlayView = ipView;
[controller presentModalViewController:self animated:NO];
}
In the overlayView, I've managed to force the takePicture method of UIImagePickerController to fire (I know this, because I can NSLog it, and I hear the sound of the camera taking a picture). The overlayView shows up just fine. However, the delegate method didFinishPickingMediaWithInfo: never gets called, and imagePickerControllerDidCancel doesn't get called either.
So, how do I either get the delegate methods to get called, or save the picture by overriding the takePicture method? (I have no idea how to capture the picture data here, and Google seems to have failed me). I can't help feeling that I've failed to understand how the guts of UIImagePickerController works, but the docs aren't overly helpful:
e.g.:
"You can provide a custom overlay view to display a custom picture-taking interface and you can initiate the taking of pictures from your code. Your custom overlay view can be displayed in addition to, or instead of, the default controls provided by the image picker interface."
or from showCameraControls:
"If you set this property to NO and provide your own custom controls, you can take multiple pictures before dismissing the image picker interface." - How do I dismiss the picker interface?
Note: the delegate is set properly in IB, so that's not the problem.
Thanks for any help you can provide!
I've found that you just have to wait "long enough" before calling takePicture, or it just silently fails. I don't have a good answer for how to determine the minimum value of "long enough" that will always work, but if you set a timer and wait five or ten seconds you should be okay. It would be nice if it returned some kind of an "I'm not ready to take a picture yet, sorry" error either directly from takePicture or through the delegate, but as far as I know it doesn't.
As an update to my own question: It turns out that I was trying to use takePicture too early. When I moved the action to a button on the overlay and sent takePicture from that button (once the picker was presented modally), the delegate methods fired as they should. I don't know if what I wanted is achievable - taking the image without having to press that button, automatically - but if it is, it will probably have to be done by sending takePicture sometime after I was trying to use it.
-(void)imageMethod:(id)sender{
imagePickerController = [[UIImagePickerController alloc]init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePopover=[[UIPopoverController alloc]initWithContentViewController:imagePickerController];
[imagePopover presentPopoverFromRect:importButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}