Yes, It might be a duplicate question of this. But since it didn’t get an answer, I will be more specific on the case and code:
I have 3 involved UIViewControllers:
WelcomeView– the first oneTakePhotoViewController– the second one who is delegate of the OverlayviewControllerOverlayViewController– custom view for the camera.
Scenario:
- User enter
WelcomeViewand clicks on a button to be transfered with segue toTakeView. UIImageViewControlleris being opened to take a photo.- The user clicks on cancel button –
didCancelCameramethod inTakePhotoViewControlleris being invoked and he returns toWelcomeView - The user leaves the app.
- The user re-opens the app and perform step 1 again.
THE IMAGE PICKER IS NOT BEING OPENED. I COULD TAKE A PHOTO AND IT’S OK – BUT THE USER CAN’T SEE WHAT HE IS TAKING.
OverlayViewController.h
@interface OverlayViewController : BaseViewController<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@property (nonatomic,weak) id<OverlayViewControllerDelegate> delegate;
@property (nonatomic,retain) UIImagePickerController *imagePickerController;
@end
OverlayViewController.m:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.imagePickerController = [[UIImagePickerController alloc] init];
self.imagePickerController.delegate = self;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
}
- (IBAction)takePicture:(id)sender {
[self.imagePickerController takePicture];
}
- (IBAction)cancelImagePicker:(id)sender {
[self.delegate didCancelCamera];
}
- (void) setupImagePicker:(UIImagePickerControllerSourceType) sourceType
{
self.imagePickerController.sourceType = sourceType;
if (sourceType == UIImagePickerControllerSourceTypeCamera)
{
self.imagePickerController.showsCameraControls = NO;
if ([[self.imagePickerController.cameraOverlayView subviews] count] ==0)
{
CGRect overlayViewFrame = self.imagePickerController.cameraOverlayView.frame;
CGRect newFrame = CGRectMake(0.0, CGRectGetHeight(overlayViewFrame)-self.view.frame.size.height-10.0, CGRectGetWidth(overlayViewFrame), self.view.frame.size.height + 10.0);
self.view.frame = newFrame;
[self.imagePickerController.cameraOverlayView addSubview:self.view];
}
}
}
- (void)finishAndUpdate
{
[NSThread detachNewThreadSelector:@selector(threadStartAnimating:) toTarget:self withObject:nil];
[self.delegate didFinishWithCamera]; // tell our delegate we are done with the camera
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self finishAndUpdate];
}
TakePhotoViewController.h
@interface TakePhotoViewController : BaseViewController<UIImagePickerControllerDelegate,UINavigationControllerDelegate,OverlayViewControllerDelegate>
@property (nonatomic, retain) OverlayViewController *overlayViewController;
@end
TakePhotoViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
// Insert the overlay
self.overlayViewController = (OverlayViewController *)[sb instantiateViewControllerWithIdentifier:@"Overlay"];
self.overlayViewController.delegate = self;
}
- (void)viewDidUnload
{
self.overlayViewController = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (void)openImagePicker {
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
[self showImagePicker:UIImagePickerControllerSourceTypeCamera];
}
else{
[self showImagePicker:UIImagePickerControllerSourceTypePhotoLibrary];
}
}
- (void)viewDidAppear:(BOOL)animated{
if (appDelegate.shouldOpenPicker){
[self openImagePicker];
}
}
- (void)showImagePicker:(UIImagePickerControllerSourceType)sourceType
{
if ([UIImagePickerController isSourceTypeAvailable:sourceType])
{
[self.overlayViewController setupImagePicker:sourceType];
[self presentViewController:self.overlayViewController.imagePickerController animated:YES completion:nil];
}
}
-(void)didCancelCamera{
[[self.overlayViewController.imagePickerController presentingViewController] dismissViewControllerAnimated:NO completion:^ {
[self performSegueWithIdentifier:@"fromTakeToWelcome" sender:self];
}];
}
I found the bug.
The method
-(void)didCancelCamerafromTakePhotoViewControlleris being called when the user clicks on- (IBAction)cancelImagePicker:(id)senderinOverlayViewController.However, somehow the code in
didCancelCameracausesviewDidAppearmethod ofTakePhotoViewControllerto be invoked again and reopen the image picker.I have no idea why
causes the viewDidAppear method of that view (TakePhoto) being recalled again.
Hope that it will help someone