Question

I'm attempting to write an application that shows the camera feed, and you can take an image from it. I've successfully set up a UIButton and a linked action method (IBAction) but I'm having trouble making it trigger the UI to save the picture. I have it all set up so when everything goes correctly it should inform the user, but instead it crashes. Any insight would be greatly appreciated.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationDidBecomeActive)
                                                 name:UIApplicationDidBecomeActiveNotification
                                               object:nil];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


-(void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIApplicationDidBecomeActiveNotification
                                                  object:nil];
}

- (void)applicationDidBecomeActive
{
    //Start the camera up

    UIImagePickerController *imageViewPickerController = [[UIImagePickerController alloc] init];

    //Hide default UI elements

    imageViewPickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
    imageViewPickerController.showsCameraControls = NO;
    imageViewPickerController.navigationBarHidden = YES;
    imageViewPickerController.toolbarHidden = YES;

    //Start the button overlay

    UIView *btnView = [[UIView alloc] initWithFrame:imageViewPickerController.view.bounds];
    btnView.opaque = NO;
    btnView.clipsToBounds = YES;

    //Start up the button
    UIButton *snapButton = [[UIButton alloc] initWithFrame:CGRectMake(-6, 504, 65, 65)];
    snapButton.alpha = 0.5;
    snapButton.transform = CGAffineTransformMakeRotation(DEGREES_RADIANS(90));
    [snapButton addTarget:snapButton action:@selector(takePhoto:) forControlEvents:UIControlEventTouchUpInside];

    //Set the button's picture
    UIImage *snapButtonImage = [UIImage imageNamed:@"Button.png"];
    [snapButton setImage:snapButtonImage forState:UIControlStateNormal];

    //Add button to the overlay
    [btnView addSubview:snapButton];

    //Overlay button view

    imageViewPickerController.cameraOverlayView = btnView;

    //Fix for iPhone 5 and make fullscreen

    CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, -55.0);
    CGAffineTransform scale = CGAffineTransformMakeScale(1.333333, 1.333333);
    CGAffineTransform rotate = CGAffineTransformMakeRotation(DEGREES_RADIANS(180));
    CGAffineTransform transform = CGAffineTransformConcat(translate, scale);
    transform = CGAffineTransformConcat(transform, rotate);
    imageViewPickerController.cameraViewTransform = transform;

    //Let's present it all

    [self presentViewController:imageViewPickerController
                       animated:NO
                     completion:NULL];


}

- (IBAction)takePhoto:(id)sender {
    [UIImagePickerController takePicture];
}

-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    // Access the uncropped image from info dictionary
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    // Save image
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}


- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    UIAlertView *alert;

    // Unable to save the image
    if (error)
        alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                           message:@"Unable to save image to Photo Album."
                                          delegate:self cancelButtonTitle:@"Ok"
                                 otherButtonTitles:nil];
    else // All is well
        alert = [[UIAlertView alloc] initWithTitle:@"Success"
                                           message:@"Image saved to Photo Album."
                                          delegate:self cancelButtonTitle:@"Ok"
                                 otherButtonTitles:nil];
    [alert show];
}

EDIT: Revised code to resolve exception.

- (void)applicationDidBecomeActive
{

    //Start the camera up

    _imageViewPickerController = [[UIImagePickerController alloc] init];

    //Hide default UI elements

    _imageViewPickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
    _imageViewPickerController.showsCameraControls = NO;
    _imageViewPickerController.navigationBarHidden = YES;
    _imageViewPickerController.toolbarHidden = YES;

    //Start the button overlay

    UIView *btnView = [[UIView alloc] initWithFrame:_imageViewPickerController.view.bounds];
    btnView.opaque = NO;
    btnView.clipsToBounds = YES;

    //Start up the button
    UIButton *snapButton = [[UIButton alloc] initWithFrame:CGRectMake(-6, 504, 65, 65)];
    snapButton.alpha = 0.5;
    snapButton.transform = CGAffineTransformMakeRotation(DEGREES_RADIANS(90));
    [snapButton addTarget:snapButton action:@selector(snapThat) forControlEvents:UIControlEventTouchUpInside];

    //Set the button's picture
    UIImage *snapButtonImage = [UIImage imageNamed:@"Button.png"];
    [snapButton setImage:snapButtonImage forState:UIControlStateNormal];

    //Add button to the overlay
    [btnView addSubview:snapButton];

    //Overlay button view

    _imageViewPickerController.cameraOverlayView = btnView;

    //Fix for iPhone 5 and make fullscreen

    CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, -55.0);
    CGAffineTransform scale = CGAffineTransformMakeScale(1.333333, 1.333333);
    CGAffineTransform rotate = CGAffineTransformMakeRotation(DEGREES_RADIANS(180));
    CGAffineTransform transform = CGAffineTransformConcat(translate, scale);
    transform = CGAffineTransformConcat(transform, rotate);
    _imageViewPickerController.cameraViewTransform = transform;

    //Let's present it all

    [self presentViewController:_imageViewPickerController
                       animated:NO
                     completion:NULL];
}

- (void)snapThat {
    [_imageViewPickerController takePicture];
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{
    // Access the uncropped image from info dictionary
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    // Save image
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}


- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
    {
    UIAlertView *alert;

    // Unable to save the image
    if (error)
        alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                           message:@"Unable to save image to Photo Album."
                                          delegate:self cancelButtonTitle:@"Ok"
                                 otherButtonTitles:nil];
    else // All is well
        alert = [[UIAlertView alloc] initWithTitle:@"Success"
                                           message:@"Image saved to Photo Album."
                                          delegate:self cancelButtonTitle:@"Ok"
                                 otherButtonTitles:nil];
    [alert show];
}

EDIT 2: Including headers

@interface TurnikitViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>

@property (strong, nonatomic) IBOutlet UIView *imageView;

@property (strong, nonatomic) UIImagePickerController *imageViewPickerController;

@end
Was it helpful?

Solution

You should have this as property:

@property (strong, nonatomic) UIImagePickerController *imageViewPickerController;

then you init that as you are doing:

_imageViewPickerController = [[UIImagePickerController alloc] init];

and when you save:

[_imageViewPickerController takePicture];

Instead now, you are not calling the method on the instance, but on the class..that is an error:

[UIImagePickerController takePicture];

And also, you are adding as target of your button, itself..instead the target is self:

[snapButton addTarget:self action:@selector(snapThat) forControlEvents:UIControlEventTouchUpInside];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top