Iphone app, IOS 5 and up.
There are similar questions to this one on SO but I haven't encountered this exact scenario so I'll ask. I'm editing an existing app that allows lets you take a photo which it resizes and sends to a web service.
I need to add the ability to take 3 photos, resize each and send to the same service. I thought it would be just a matter of repeating what was already in the app but it uses the UIImagePickerController which apparently only allows one photo per use.
So the way it works is that there's a 'Take Photo' button which calls the method below. Once that photo is taken another button appears that says 'Take another photo' (I added this button) and I have it calling the same method but it is just copying over the previous photo, which is to be expected really. How should I best alter this to accommodate 3 photos?
This is the takephoto method that I'm calling.
- (IBAction)takePhoto:(id)sender
{
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:YES completion:NULL];
}
check this https://developer.apple.com/library/ios/samplecode/photopicker/Introduction/Intro.html
, check the take photo part of this demo project.
Eventually figured out how to do this. I added a tag to the button calling the method, through IB.
Then in the takephoto method I assigned the imagePickerController a tag based on the tag of the button that tapped. Like this:
- (IBAction)takePhoto:(id)sender
{
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
if([sender tag] == 2)
{
imagePickerController.view.tag = 2;
}
//And so on...
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:YES completion:NULL];
}
Then in the ImagePickerController didFinishedPickingMediaWithInfo method:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
if(picker.view.tag == 2)
{
//Do stuff here
}
}
So, I'll probably have to create three different buttons for each of the three possible photos, I'm sure there's a better way than that but it should work.
Related
Hi Im making altered reality app. My main controller is derived from UIImagePickerController. Here is how I create it:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.overlayController) {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
self.sourceType = UIImagePickerControllerSourceTypeCamera;
self.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
self.cameraDevice = UIImagePickerControllerCameraDeviceRear;
self.showsCameraControls = false;
self.allowsEditing = false;
self.overlayController = [[[ControlsViewController alloc] initWithNibName:#"ControlsViewController" bundle:[NSBundle mainBundle] picker:self] autorelease];
[self.view addSubview:self.overlayController.view]; // need to add as subview otherwise mouse events captured by UIImagePickerController
self.overlayController.view.frame = CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height);
}
}
[cameraControls setCamera:self];
}
Basically controller exists through whole lifecycle of the app. Now when I take photo with code below most of the time it works fine but sometime didFinishPickingMediaWithInfo isn't called. Usual behavior is I see camera focus starts adjust blur-in/out and then it stabilizes but didFinishPickingMediaWithInfo will never be called. Looks like if camera goes into some kind of calibration mode it may not fire this event. Anyone have solution? I hope there is maybe some kind of extra callback (like error processing Im missing).
I can even hear camera shutters simulated sound interrupted when camera goes into that weird calibration mode.
//self.cameraPicker points to the instance of my main controller that I created earlier
-(void) setCamera:(UIImagePickerController *)picker {
self.cameraPicker = picker;
picker.delegate = self;
}
-(void) takePicture {
[self.cameraPicker takePicture];
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSLog(#"Picture ready");
}
I'm having a slight issue here.
I have a basic view which has two UIButtons and two UIImageViews, I would like my users to be able to take two different photos, and these to be attached to their respective UIImageView.
Right now this works fine for the first UIButton/image, but not with a second.
.h
#interface ViewController : UIViewController <UIImagePickerControllerDelegate> {
// First button/imageview
UIImagePickerController *picker;
UIImage *image;
// Second button/imageview
UIImagePickerController *picker2;
UIImage *image2;
}
.m
-(IBAction)TakePhoto
{
picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
[picker setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentViewController:picker animated:YES completion:NULL];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
image2 = [info objectForKey:UIImagePickerControllerOriginalImage];
[imageField2 setImage:image2];
[self dismissViewControllerAnimated:YES completion:NULL];
}
This all works great but my question is how can I hook up the second picker to a new imagePickerController method so that my user can take two different photos on this view? I know that if I created a new action with the picker2 information it will still point to the one imagePickerController method, creating a second method and renaming this to suit does not work.
Any advice & help would be greatly appreciated.
Jamie
You don't need two UIImagePickerControllers to do it.
Take a look at takePicture method of UIImagePickerController which programatically initiates still image capture.
You can initiate additional captures after receiving imagePickerController:didFinishPickingMediaWithInfo: delegate callback.
PhotoPicker is a sample project from Apple which does exactly what you are trying to do.
Hope it helps.
When i try to load camera from my code, camera preview is black. If I wait for 10-20 seconds it will show real camera preview. I found several questions and some of them suggest that running some other code in background should be the reason for this. However I don't have any code running in background.
How should I fix this?
This is my code where I run camera
UIImagePickerController *photoPicker = [[UIImagePickerController alloc] init];
photoPicker.delegate = self;
photoPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:photoPicker animated:YES completion:NULL];
About 5 months ago my team discovered a memory leak with UIImageViewController in iOS7. Each instantiation slowed down the app exponentially (i.e. first alloc-init had a 1 second delay, second had a 2 second delay, third had a 5 second delay). Eventually, we were having 30-60 delays (similar to what you're experiencing).
We resolved the issue by subclassing UIImagePickerController and making it a Singleton. That way it was only ever initialized once. Now our delay is minimal and we avoid the leak. If subclassing isn't an option, try a class property in your viewController and just lazy load it like so.
-(UIImagePickerController *)imagePicker{
if(!_imagePicker){
_imagePicker = [[UIImagePickerController alloc]init];
_imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
return _imagePicker;
}
Then you can just call it later like:
[self presentViewController:self.imagePicker animated:YES completion:nil];
Had this myself - it happens if something is running on the main dispatch thread - are you resizing images by any chance?
It puts the preview onto the main thread and if something is using it, you get a black screen. It's a bug and the workaround is to either take over the main thread or to disable the photo picker until the queue is free
This Should work for you:
- (void)cameraViewPickerController:(UIImagePickerController *)picker
{
[self startCameraControllerFromViewController: picker
usingDelegate: self];
}
- (BOOL) startCameraControllerFromViewController: (UIViewController*) controller
usingDelegate: (id <UIImagePickerControllerDelegate,
UINavigationControllerDelegate>) delegate {
if (([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera] == NO)
|| (delegate == nil)
|| (controller == nil))
return NO;
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
// Displays a control that allows the user to choose movie capture
cameraUI.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeImage, (NSString *) kUTTypeMovie,nil];
// Hides the controls for moving & scaling pictures, or for
// trimming movies. To instead show the controls, use YES.
cameraUI.allowsEditing = NO;
cameraUI.delegate = delegate;
[controller presentViewController:cameraUI animated:YES completion:nil];
return YES;
}
I am trying to implement a feature of taking X amount of pictures programmatically after entering a UIViewController for both the iPhone and iPad. I looked into UIImagePickerController but I do not want to present the camera controls and have the user hit a button to capture only one photo. Is there a way to capture X amount of photos once entering a UIViewController and storing all the photos in the end for future reference in one go?
Edit:
-(void)viewDidAppear:(BOOL)animated
{
// Create image picker controller
picker = [[UIImagePickerController alloc] init];
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
[picker setSourceType:UIImagePickerControllerSourceTypeCamera];
}
else
{
[picker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}
// Set source to the camera
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
// Delegate is self
picker.delegate = self;
// Allow editing of image ?
picker.allowsEditing = NO;
//picker.showsCameraControls = NO;
// Show image picker
[picker animated:YES completion:nil];
}
straight away with takePicture you can not take multiple snaps, for that you have to use some video recording and get snap out of it for particular frame or time, for you more reference you can use this apple documentation for bulk snaps AVFoundation Programming Guide
You can try something like this:
int numberOfPhotos = 3; // Number of photos you want to take.
for ( int i = 0; i < numberOhPhotos; i++ )
{
// Note that you should use some sort of a pause in between each photo.
[picker takePicture];
}
I use standart image picker to make some camera photo.
When user makes photo image picker shows him the Preview screen with 2 buttons "Retake" and "Use".
How to detect that Preview screen is active now or "Retake" button pressed? Is it possible ? Are the useful properties or events? Something like when image source is library the is property - allows editing, which shows similar screen .
UIImagePickerController * imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
A bit after the fact, but maybe someone is still seeking this answer like I was. If you want continue using the native camera controls, you can check the subviews of the ImagePickerController to determine if the post-record view is showing.
BOOL videoTaken = NO;
for (UIView *aView in self.imagePickerController.view.subviews[0].subviews[0].subviews[0].subviews)
{
if ([aView isKindOfClass:NSClassFromString(#"PLTileContainerView")])
{
videoTaken = YES;
break;
}
}
The "PLTileContainerView" is the subview that contains the editing slider that lets you view your video frame by frame, so if it's present, that means your video has already recorded.
For use:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissModalViewControllerAnimated:NO];
NSString *type = [info objectForKey:#"UIImagePickerControllerMediaType"];
if ([type isEqualToString:#"public.movie"]) {
} else {
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
}
For Cancel you don't have a way of detecting it (other than subclassing UIImagePickerController, which may be prohibited, or other way that I'm not aware), but for sure the second cancel is detectable :
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissModalViewControllerAnimated:YES];
}