7

I am creating an iPad app that has several pictures (UIImageViews) in a horizontal scrollview. I want to allow the user to be able to save the images to their Photo Library when they tap on one of the UIImageViews. I like the way Safari handles this matter: you just tap and hold until a pop up menu appears and then click save image. I know there is the "UIImageWriteToSavedPhotosAlbum". But I am a newbie to iOS development and I'm not too sure where to go with it and where to put it (i.e. how to detect which image was tapped).

From what I have found, I have seen people use UIImage instead of UIImageView. Do I need to convert my view to UIImage? If so, how? How do I detect when the user taps the images, and which UIImageView was tapped? If you could point me in the right direction, and maybe some examples I would greatly appreciate it.

DShah
  • 9,768
  • 11
  • 71
  • 127
Brian
  • 819
  • 4
  • 20
  • 35

4 Answers4

32

You can use the image property of a UIImageView to get the current image:

UIImage* imageToSave = [imageView image]; // alternatively, imageView.image

// Save it to the camera roll / saved photo album
UIImageWriteToSavedPhotosAlbum(imageToSave, nil, nil, nil);
bosmacs
  • 7,341
  • 4
  • 31
  • 31
  • Thanks for the quick reply. But how do I detect which UIImageView was tapped? Is there a way to make a pop up appear when the user taps the image that allows the user to select a button to save? And when the "Save" button gets pressed, I would put your statement in that IBAction, right? – Brian Nov 16 '10 at 19:47
  • You could wire the 'touch up inside' event on your UIImageView in Interface Builder to an action method you implement (this can also be done programmatically), such as `-(void)touchedImageView:(id)sender`, in which case `sender` would be the view that was touched. From there, you could present a menu (such as a `UIActionSheet`) to decide whether to save the image. – bosmacs Nov 16 '10 at 20:05
  • I have the code down, but I'm not seeing any of the 'touch' events in Interface Builder. With one of my UIImageViews selected, I go to the Inspector window, then the Connections tab, right? I see the touch events when a button is selected but not a UIImageView. Should I just make all of these UIImageViews into buttons? – Brian Nov 16 '10 at 20:29
  • Sorry, forgot about that. You might try the advice in this question: http://stackoverflow.com/questions/855095/how-can-i-detect-the-touch-event-of-an-uiimageview -- either subclass UIImageView to override the touch* methods, or place a hidden button over each UIImageView, and wire the touch events to the button. – bosmacs Nov 17 '10 at 14:09
  • I played around with that a little yesterday, but my problem is that this is in a scroll view. So if the user first touches the button and then moves to scroll, it doesn't scroll. I googled around a bit with that issue, but I have yet to find anything that worked. Still working on it though. Thanks for your help. – Brian Nov 17 '10 at 15:45
  • I think I have figured it out. For anyone who sees this and is having the same problem, here is what I did: – Brian Nov 17 '10 at 16:36
  • I changed the UIImageViews to custom UIButtons and set the image property to my image. Set the scrollviews delaysContentTouches property to YES (i.e. [scrollView setDelaysContentTouches:YES];). This allows the scroll view to distinguish between a "click" and a "swipe". When the user "clicks" the button, the ActionSheet appears. Here is a link I found useful with ActionSheet: http://ykyuen.wordpress.com/2010/04/14/iphone-uiactionsheet-example/ The reference at the bottom of that page is also useful. Thanks again Bosmacs. – Brian Nov 17 '10 at 16:46
  • what if i have a `subview` in the `imageView`, can i save them as one image? – Dvir Levy Jun 11 '12 at 09:05
4
- (IBAction)TakePicture:(id)sender {


    // Create image picker controller
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];

    // Set source to the camera
    imagePicker.sourceType =  UIImagePickerControllerSourceTypeCamera;


    // Delegate is self
    imagePicker.delegate = self;


    OverlayView *overlay = [[OverlayView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGTH)];

   // imagePicker.cameraViewTransform = CGAffineTransformScale(imagePicker.cameraViewTransform, CAMERA_TRANSFORM_X, CAMERA_TRANSFORM_Y);

    // Insert the overlay:
    imagePicker.cameraOverlayView = overlay;

   // Allow editing of image ?
    imagePicker.allowsImageEditing = YES;
    [imagePicker setCameraDevice:
     UIImagePickerControllerCameraDeviceFront];
    [imagePicker setAllowsEditing:YES];
    imagePicker.showsCameraControls=YES;
    imagePicker.navigationBarHidden=YES;
    imagePicker.toolbarHidden=YES;
    imagePicker.wantsFullScreenLayout=YES;


    self.library = [[ALAssetsLibrary alloc] init];


    // Show image picker
    [self presentModalViewController:imagePicker animated:YES];
}





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




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


    // save image to custom album
    [self.library saveImage:image toAlbum:@"custom name" withCompletionBlock:^(NSError *error) {
        if (error!=nil) {
            NSLog(@"Big error: %@", [error description]);
        }
    }];

    [picker dismissModalViewControllerAnimated:NO];


}



- (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];
}



- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex
{
    // After saving iamge, dismiss camera
    [self dismissModalViewControllerAnimated:YES];
}
raj
  • 163
  • 1
  • 3
3

In regards to the part of your question asking how to detect which UIImageView was tapped, you can use code like the following:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

 [super touchesEnded:touches withEvent:event];
 UITouch *touch = [touches anyObject];
 CGPoint touchEndpoint = [touch locationInView:self.view]; 
 CGPoint imageEndpoint = [touch locationInView:imageview];
 if(CGRectContainsPoint([imageview frame], touchEndpoint))
 {
 do here any thing after touch the event.

  }
}
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
user867380
  • 31
  • 1
1

In Swift:

    // Save it to the camera roll / saved photo album
    // UIImageWriteToSavedPhotosAlbum(self.myUIImageView.image, nil, nil, nil) or 
    UIImageWriteToSavedPhotosAlbum(self.myUIImageView.image, self, "image:didFinishSavingWithError:contextInfo:", nil)

    func image(image: UIImage!, didFinishSavingWithError error: NSError!, contextInfo: AnyObject!) {
            if (error != nil) {
                // Something wrong happened.
            } else {
                // Everything is alright.
            }
    }
King-Wizard
  • 15,628
  • 6
  • 82
  • 76