Problem opening new ViewController after UIImagePickerController - iphone

I am trying to open up a new view (UnprocessedPhotoViewController) immediately after the delegate function for my UIImagePickerController returns a "didFinishPickingImage".
Unfortunately, it appears that I can either open the UIImagePickerController modal view, or switch to the UnprocessedPhotoViewController as a modal, but not both sequentially.
In the code below, a button press activates the pickPhoto IBAction. This code activates the UIImagePickerController successfully. After the user selects an image, the didFinishPickingImage delegate function is called, which stores the image to a variable, attempts to close the UIImagePickerController modal and open the UnprocessedPhotoViewController in a new modal.
Note: If I comment out the ImagePicker and run "showPhoto" directly, the UnprocessedPhotoViewController shows successfully. Also, if I make a new button to launch either view it works successfully, but I am unable to launch the views sequentially. I would expect that after a user selected the image, the new view would be launched which would allow the user to process the image.
What is the correct way to guarantee that the ImagePicker modal closes and then to open the UnprocessedPhotoViewController?
Thanks!!!
Code:
- (IBAction)pickPhoto:(id)sender{
//TODO: To be replaced with the gallery control launching code
// Load Image Selection Code
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:self.imgPicker animated:YES];
}
// Dummy function assumes you either picked (or took a picture =D) of Angie and moves you right to the unprocessed viewing screen.
- (void) showPhoto{
// Start new view controller
[self dismissModalViewControllerAnimated:YES];
UnprocessedPhotoViewController *upViewController = [[UnprocessedPhotoViewController alloc] initWithNibName:#"UnprocessedPhotoViewController" bundle:nil];
upViewController.imageView.image = selectedImage;
upViewController.delegate = self;
upViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:[upViewController animated:YES]];
[upViewController release];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img {
selectedImage = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
[self dismissModalViewControllerAnimated:YES];
[self showPhoto];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}

Implement viewDidAppear in your root view controller and based on member data decide to call showPhoto or not. The following example simply re-presents the UIImagePicker but any new modal view will work. viewDidAppear is called any time your root view controller’s view appears so you have to make sure the context is known when it is called. But it is the deterministic way to know that the modal view controller is gone.
- (IBAction) showPicker: (id) sender
{
UIImagePickerController* picker = [[[UIImagePickerController alloc] init] autorelease];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
picker.allowsEditing = YES;
[self presentModalViewController:picker animated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
imageChosen = YES;
[self dismissModalViewControllerAnimated:YES];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
imageChosen = NO;
[self dismissModalViewControllerAnimated:YES];
}
- (void) viewDidAppear: (BOOL) animated
{
if ( imageChosen )
{
[self showPicker: self];
}
}

Another way to do this is to wrap the built-in dismissal animation with your own animation, and then catch the animationDidStop "event." This creates a composite animation, so when the built-in animation is done, your (empty) wrapper animation finishes you and alerts you that you're done.
This is slightly cleaner than the other answer here, IMO, as you don't need to keep a state variable or override viewDidAppear: (in my app, the view controller presenting the picker is quite a few objects removed from the utility code that handles picker management, and that would mean any view controller using my shared utility would have to override viewDidAppear:, or else fail to work):
-(void)dismissalAnimationDone:(NSString*)animationID
finished:(BOOL)finished context:(void*)context
{
UIImage* image = (UIImage*) context;
// present controllers as you please
}
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
[UIView beginAnimations:#"dismissal wrapper" context:image];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(dismissalAnimationDone:finished:context:)];
[self.delegate dismissModalViewControllerAnimated:YES];
[UIView commitAnimations];
}

Related

iOS 7 UIImagePickerController Camera Covered with Static image

iOS 7 using UIImagePickerController to take picture twice, at second time will show a static image covered the camera, how to reset the camera.
I'm try to take picture one by one, and keep take 5 pictures.
It works on iOS6.
on iOS7, it works fine at the first time, but when it take picture at second time, it will show a static dark image on screen, how to clear or reset it, although take picture works, but user can't see what will capture with camera.
bool fistTimeToShow = YES;
-(void) viewDidAppear:(BOOL)animated{
if (fistTimeToShow) {
fistTimeToShow = NO;
self.imagePickerController = nil;
[self tackImage];
}
}
-(void)tackImage{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
self.imagePickerController = [[UIImagePickerController alloc]init];
self.imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
self.imagePickerController.showsCameraControls = YES;
self.imagePickerController.delegate = self;
[self presentViewController:self.imagePickerController animated:NO completion:nil];
}
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSLog(#"====== imagePickerController:didFinishPickingMediaWithInfo ======");
[self.imagePickerController dismissViewControllerAnimated:NO completion:nil];
//...deal with the image capture...
self.imagePickerController = nil;
[self tackImage];
}
Update
I change the dismiss function to put the [self tackImage]; in block. And now it always show the fist image took.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSLog(#"====== imagePicker: didFinish ======");
self.imagePickerController = nil;
[self dismissViewControllerAnimated:NO completion: ^{
[self tackImage];
}];
}
I'm trying to find a way to clear the image. But I don't know where the image saved yet.
Update2
use
[self performSelector:#selector(presentCameraView) withObject:nil afterDelay:1.0f];
and function
-(void)presentCameraView{
[self presentViewController:self.imagePickerController animated:NO completion:nil];
}
to replace. [self presentViewController:self.imagePickerController animated:NO completion:nil]; it works on my device anyway, but I don't even know why.
Update3
I have set the userInteractionEnabled to NO when Delay:1.0f to avoid other problems, and may be also need set the navigationBar and tabBar for specifically use.
I had exactly the same issue under iOS 7 using Xamarin.iOS.
What has helped, is adding GC.Collect() in didFinishPickingMediaWithInfo method.
In C# GC.Collect() "cleans up" the memory from unused/disposed objects.
For sure, there's no direct equivalent for that in Obj-C, but that may shed some light on your problem also (it could be memory-related).

Dismissing camera view crashes app

When I try to dismiss my UIImagePickerController, it crashes the app. the error is: "Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'preferredInterfaceOrientationForPresentation must return a supported interface orientation!'"
I have the preferred interface orientation set in my view controller.
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
- (BOOL) shouldAutorotate {
return YES;
}
Here is the method I'm calling to bring up the camera, this works fine for adding the camera, but like I said, crashes when I try to remove the camera.
-(IBAction)addCamera:(id)sender
{
self.cameraController = [[UIImagePickerController alloc] init];
self.cameraController.sourceType = UIImagePickerControllerSourceTypeCamera;
self.cameraController.cameraViewTransform = CGAffineTransformScale(self.cameraController.cameraViewTransform,
1.13f,
1.13f);
self.cameraController.showsCameraControls = NO;
self.cameraController.navigationBarHidden = YES;
self.wantsFullScreenLayout = YES;
ar_overlayView = [[UIView alloc] initWithFrame:CGRectZero];
self.view = ar_overlayView;
[self.cameraController setCameraOverlayView:ar_overlayView];
[self presentViewController:cameraController animated:NO completion:nil];
[ar_overlayView setFrame:self.cameraController.view.bounds];
}
-(IBAction)back:(id)sender
{
[ar_overlayView removeFromSuperview];
[cameraController dismissViewControllerAnimated:NO completion:nil];
}
Alright, found the solution, it was really simple, I just changed my back method to:
[self dismissModalViewControllerAnimated:YES];
Now my camera goes away and I can see my original view when I press the back button.
I still haven't figured out what was causing the original problem as I've gone through the info.plist and the methods for supported orientations, but this accomplishes what I wanted.
I'm still curious as to what was causing the error though if anyone has any ideas.
You can try remove this method:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
It will fix it.but sometimes it will lead to reduce stateBar height.
You cannot remove a UIViewController's main view from its superview.
Instead of this:
self.view = ar_overlayView;
Try this:
[self.view addSubview:ar_overlayView];
Then you will be able to remove it from the superview correctly.
You should be using the didFinishPickingMedieWithInfo method similar to below and use [self dismissModalViewControllerAnimated:YES];
-(void) imagePickerController:(UIImagePickerController *) picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
NSLog(#"Camera");
}
else {
NSLog(#"Album");
}
[self dismissModalViewControllerAnimated:YES];
}
I don't think you need to add ar_overlayView to the current view yourself if it's a camera overlay.
Here's what your code is doing now:
Add ar_overlayView to the current view
Add ar_overlayView as the camera's overlay view
Show the camera view (modal)
At this point, ar_overlayView is being displayed twice. When you send it the removeFromSuperview message on dismissing the camera view, it might be getting confused since it's in two view hierarchies at the same time.
Skipping the self.view = ar_overlayView; or [self.view addSubview:ar_overlayView]; lines should fix the problem.
Also, dismissViewControllerAnimated:completion: should be sent to the same object that presentViewController:animated:completion was called on (self in this case):
-(IBAction)addCamera:(id)sender
{
// -- snip -- //
ar_overlayView = [[UIView alloc] initWithFrame:self.cameraController.view.bounds];
[self.cameraController setCameraOverlayView:ar_overlayView];
[self presentViewController:self.cameraController animated:NO completion:nil];
}
-(IBAction)back:(id)sender
{
[self dismissViewControllerAnimated:NO completion:nil];
}

iPhone - Remove status bar programmatically

I have made an app that implements the iPhone's camera.
When the user finishes picking their image, the status bar reappears!
How would I make sure that the status bar stays hidden?
Here is my code:
-(IBAction)pickImage:(id)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentModalViewController:picker animated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissModalViewControllerAnimated:YES];
background.image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
If i am doing anything wrong, please point it out!
Thanks,
Rafee
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
You may opt for another animation style if at all.
In iOS 7, there is a method on UIViewController, "prefersStatusBarHidden". To hide the status bar, add this method to your view controller and return YES:
- (BOOL) prefersStatusBarHidden
{
return YES;
}
In this case,We are using 2 steps
In first step:
Add in info.plist: "View controller-based status bar appearance" with value "NO"
In Second step: Use/call this code with delegate of UIImagePickerController
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if([navigationController isKindOfClass:[UIImagePickerController class]])
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
With iOS 7 and later, you can use the following code to hide and unhide the status bar,
#interface ViewController()
#property (nonatomic, getter=isStatusBarHidden) BOOL statusBarHidden;
#end
#implementation ViewController
... other codes
- (BOOL)prefersStatusBarHidden {
return self.isStatusBarHidden;
}
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
return UIStatusBarAnimationFade;
}
- (void)hideStatusBar {
self.statusBarHidden = YES;
[self setNeedsStatusBarAppearanceUpdate];
}
- (void)showStatusBar {
self.statusBarHidden = NO;
[self setNeedsStatusBarAppearanceUpdate];
}
#end
There seems to be a bug in the dismiss mechanism of UIViewController associated with UIImagePicker, with a sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum.
The moment of the call to dismissModalViewController (plus the method with completion:) the UIApplication's status bar hidden property instantly changes from YES to NO, and it is drawn at the moment of stepping over dismiss...
This is only really obvious for apps that use a full-screen view. My current app project does, plus I control the frame of the view controller's view before presenting, so the UIImagePicker is NOT full screen. This made the bug VERY obvious. I spent 4-5 hours determining the cause, and this was the final certain conclusion, and the bug does NOT occur for sourceType Camera nor PhotoLibrary.
So if you want a perfectly full-screen app and want to present a bug-free UIImagePicker, avoid UIImagePickerControllerSourceTypeSavedPhotosAlbum
Grand central dispatch is your friend, using this method you won't see the status bar appear at all when the picker is displayed or afterwards
- (void)hideStatusBar
{
if ([self respondsToSelector:#selector(setNeedsStatusBarAppearanceUpdate)])
{
[self performSelector:#selector(setNeedsStatusBarAppearanceUpdate)];
}
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self hideStatusBar];
double delayInSeconds = 0.2;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self hideStatusBar];
});
}

Passing UIImage to second view controller lags transition

I'm using a UIImagePickerController to select an image from my photo album. Once I've selected the image, I'm passing the image through to a second view controller and displaying it in a UIImageView. See code below:
First view controller:
- (IBAction)selectPhoto
{
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentModalViewController:self.imagePicker animated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UploadViewController *uploadViewController = [[UploadViewController alloc] initWithNibName:#"UploadViewController" bundle:nil];
[uploadViewController setImage:[info objectForKey:#"UIImagePickerControllerOriginalImage"]];
[picker pushViewController:uploadViewController animated:YES];
}
Second view controller:
- (void)viewDidLoad
{
[super viewDidLoad];
// Set the image view image
imageView.image = self.image;
}
The code does the job, however, when I push from the image picker to my second view controller, it lags as it's transitioning.
Ideally I would like a smooth transition but I would be happy if it just waited half a second or something and then moves smoothly.
Can any explain why this could be happening and how/if I can get around it?
Thanks.
The delay is probably from rendering the image, you could try having your UploadViewController's initial view contain an activity spinner then actually set the image in the viewDidAppear method, this method should be called after the animation is completed.
Try with this , here timer is introduced in order to provide delay(0.5sec) ,
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[NSTimerscheduledTimerWithTimeInterval:0.5 target:self selector:#selector(timerAction:) userInfo:info repeats:NO];
}
-(void)timerAction:(NSTimer *)timer
{
UploadViewController *uploadViewController = [[UploadViewController alloc] initWithNibName:#"UploadViewController" bundle:nil];
[uploadViewController setImage:[[timer userInfo]objectForKey:#"UIImagePickerControllerOriginalImage"]];
[picker pushViewController:uploadViewController animated:YES];
[uploadViewController release];
}

Record Video/Take Picture switch in iPhone app?

So i got a iphone app that is a button and when you pressed it i want the camera view to pop up and i want to give the user a choice to take a picture or a video like in the default camera app the one switch thing.
Thanks!
What you are looking for is something called 'UIImagePickerController'
-(void) getPhoto:(id) sender {
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
if((UIButton *) sender == choosePhotoBtn) {
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
} else {
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
[self presentModalViewController:picker animated:YES];
}
This method is the what would be called when you press your button(s), what i am doing here is I have two buttons, choosePhotoBtn, and takePhotoBtn, the both link to the same method.
If the button that was pressed (the sender) is choosePhotoBtn, then UIImagePickerControllerSourceTypeSavedPhotosAlbum is set as the UIImagePickerController's source type.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissModalViewControllerAnimated:YES];
bannerImage.image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissModalViewControllerAnimated:YES];
}
These two methods are delegate methods. They get called when the modelViewController holding the UIImagePickerController is dismissed.
I would recommend this site, as it has a brilliant tutorial on how to use these functions.
http://icodeblog.com/2009/07/28/getting-images-from-the-iphone-photo-library-or-camera-using-uiimagepickercontroller/
This is where i learnt how to use these classes, it seems like the site has had a wordpress comment attack on it at the moment, and firefox is blocking it for me, but if u can get to the page. Its a great resource.