iOS: Image Will Not Delete From Array

Go To StackoverFlow.com

0

I'm working on an app that behaves like a photo gallery, and I'm implementing the option to have the user delete photos from their gallery. To accomplish this, I decided to place an invisible button over each picture. When the user hits an "Edit" button, the hidden delete buttons over each picture become active. I'm using the same IBOutlet over each of the hidden buttons for simplicity, and I've tagged each button appropriately in Interface Builder. When the user taps the button over the picture, an alert view appears asking if they really want to delete it. If they click yes, I call removeObjectAtIndex. Here is the code I'm using:

- (IBAction)deleteButtonPressed:(id)sender {
    NSLog(@"Sender is %@", sender);
    UIAlertView *deleteAlertView = [[UIAlertView alloc] initWithTitle:@"Delete"
                                                              message:@"Are you sure you want to delete this photo?"
                                                             delegate:self
                                                    cancelButtonTitle:@"No"
                                                    otherButtonTitles:@"Yes", nil];
    [deleteAlertView show];
    int imageIndex = ((UIButton *)sender).tag;
    deleteAlertView.tag = imageIndex;

}

- (void)alertView: (UIAlertView *) alertView 
clickedButtonAtIndex: (NSInteger) buttonIndex
{


    if (buttonIndex != [alertView cancelButtonIndex]) {
        NSLog(@"User Clicked Yes.");
        [self.array removeObjectAtIndex: alertView.tag];
    }
    [self.user setObject:array forKey:@"images"];
}

The issue here is that when I click "Yes" in the alert view, nothing happens. However, if I tap on the image and click "Yes" a second time, the app crashes, and the debug states: Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray removeObjectAtIndex:]: index (0) beyond bounds (0)' So, I'm not sure where to go from here, I'm still very new to programming and everything looks correct to me. Any help is much appreciated, thanks!

Here is how I add them into the array:

////start of saving////
- (void)viewWillAppear:(BOOL)animated
{

    self.user = [NSUserDefaults standardUserDefaults];

    self.array = [[self.user objectForKey:@"images"]mutableCopy];
    while(self.array == nil)
    {
        [self.user setObject:[NSMutableArray arrayWithObject:@""] forKey:@"images"];
        self.array = [[self.user objectForKey:@"images"]mutableCopy];
        NSLog(@"%@",@"attempting to create an array to store the images in");
    }

}

- (void)applicationDidEnterBackground:(UIApplication*)application {
    NSLog(@"Image on didenterbackground: %@", imageView);
    self.array = [NSMutableArray arrayWithObject:[NSData dataWithData:UIImagePNGRepresentation(imageView.image)]];

    [self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView2.image)]];
     [self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView3.image)]];
      [self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView4.image)]];
       [self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView5.image)]];

            [self.user setObject:self.array forKey:@"images"];
    [user synchronize];

            }

- (void)viewDidLoad
    {
        self.user = [NSUserDefaults standardUserDefaults];
        NSLog(@"It is %@", self.user);
        self.array = [[self.user objectForKey:@"images"]mutableCopy];
        imageView.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:0]];
        imageView2.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:1]];
        imageView3.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:2]];
        imageView4.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:3]];
        imageView5.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:4]];
        imageView6.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:5]];


        UIApplication *app = [UIApplication sharedApplication];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(applicationDidEnterBackground:)
                                                     name:UIApplicationDidEnterBackgroundNotification
                                                   object:app];

        backToGalleryButton.hidden = YES;
        tapToDeleteLabel.hidden = YES;
        deleteButton1.hidden = YES;
        [super viewDidLoad];

    }

- (void)viewDidUnload
    {
        self.user = nil;
    }

////end of saving



///// shows the hidden and invisible "delete" button over each photo.
- (IBAction)editButtonPressed:(id)sender {
    grabButton.hidden = YES;
    editButton.hidden = YES;
    backToGalleryButton.hidden = NO;
    tapToDeleteLabel.hidden = NO;
    deleteButton1.hidden = NO;
}


- (IBAction)deleteButtonPressed:(id)sender {
    NSLog(@"Sender is %@", sender);
    UIAlertView *deleteAlertView = [[UIAlertView alloc] initWithTitle:@"Delete"
                                                              message:@"Are you sure you want to delete this photo?"
                                                             delegate:self
                                                    cancelButtonTitle:@"No"
                                                    otherButtonTitles:@"Yes", nil];
    [deleteAlertView show];
    int imageIndex = ((UIButton *)sender).tag;
    deleteAlertView.tag = imageIndex;

}

- (void)alertView: (UIAlertView *) alertView 
clickedButtonAtIndex: (NSInteger) buttonIndex
{


    if (buttonIndex != [alertView cancelButtonIndex]) {
        NSLog(@"User Clicked Yes.");
        NSLog(@"Array: %@, index: %d", self.array, alertView.tag);
        [self.array removeObjectAtIndex: alertView.tag];
    }
    [self.user setObject:array forKey:@"images"];
}
@end

EDIT: This is the code I use to put the objects into the UIImageView from the users camera roll:

- (IBAction)grabImage {
    self.imgPicker = [[UIImagePickerController alloc] init];
    self.imgPicker.delegate = self;
    self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        _popover = [[UIPopoverController alloc] initWithContentViewController:imgPicker];
        [_popover presentPopoverFromRect:self.imageView.bounds inView:self.imageView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    } 

    else {
        [self presentModalViewController:imgPicker animated:YES];
    }
    [self.imgPicker resignFirstResponder];
}
// Sets the image in the UIImageView
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
    if (imageView.image == nil) {
        imageView.image = img;
        [picker dismissModalViewControllerAnimated:YES];
        [self.popover dismissPopoverAnimated:YES];
        return;

    }

    if (imageView2.image == nil) {
        imageView2.image = img;
        [picker dismissModalViewControllerAnimated:YES];
        [self.popover dismissPopoverAnimated:YES];
        return;
    }

    if (imageView3.image == nil) {
        imageView3.image = img;
        [picker dismissModalViewControllerAnimated:YES];
        [self.popover dismissPopoverAnimated:YES];
        return;
    }

    if (imageView4.image == nil) {
        imageView4.image = img;
        [picker dismissModalViewControllerAnimated:YES];
        [self.popover dismissPopoverAnimated:YES];
        return;
    }

}

When I added NSLog(@"Array: %@, index: %d", self.array, alertView.tag); just before removeAtIndex the console says 2012-04-03 18:39:39.066 AppName[1631:f803] Array: (null), index: 0. Could that be the cause? I'm not sure why it would be, I think the code looks fine.

2012-04-03 23:45
by Henry F
It appears your array is empty. Show where you added the objects to it - borrrden 2012-04-03 23:49
Can you print out values just before removeObjectAtIndex:? ...something like NSLog(@"Array: %@, index: %d", self.array, alertView.tag);Phillip Mills 2012-04-03 23:50
@borrrden sure, I'll post most of my code from the file - Henry F 2012-04-04 00:00
@Phillip, Yes, the output is Array: ( "" ), index: - Henry F 2012-04-04 00:00
Sounds like you forgot to refresh the screen after deleting the array element - Hot Licks 2012-04-04 00:37
@HotLicks Ah okay thanks. I thought that [self.user setObject:array forKey:@"images"]; would of done the trick, how else could I refresh the screen - Henry F 2012-04-04 00:41
Well, I presume you wrote the logic in viewDidLoad. Don't you think that logic needs to be repeated somehow - Hot Licks 2012-04-04 02:56
@HotLicks Definitely, thanks a lot. I copied the code from viewDidLoad and added it under [self.array removeObjectAtIndex: alertView.tag];. That made all of the images after selecting yes in the alert view, but hey, thats progress! Thanks - Henry F 2012-04-04 03:59


2

There are many oddities with this code but I think the problem is that you are not calling super on your viewwillappear and viewdidload functions. I would get rid of your viewWillAppear method as it serves no purpose.

2012-04-04 00:29
by borrrden
Alright thank you. I deleted viewWillAppear, and added [super viewDidLoad] in viewDidLoad. However, the issue is still occurring. When I added NSLog(@"Array: %@, index: %d", self.array, alertView.tag); just before removeAtIndex the console says 2012-04-03 18:39:39.066 AppName[1631:f803] Array: (null), index: 0. Could that be the cause? I'm not sure why it would be, I think the code looks fine - Henry F 2012-04-04 00:38
probably because you never add them unless the app goes to sleep. where are they supposed to come fro - borrrden 2012-04-04 00:41
The user ads them from their camera roll, I will post the code that I use to do that in the OP - Henry F 2012-04-04 00:42
That adds them to the UI but not to the array, you need to add then to the array too! Also you need to alloc the array before you use it if you get nil from userdefaults, which will happen the first tim - borrrden 2012-04-04 00:50
Ah alright that makes sense, I can believe I didn't already do that, I will do that right now. Should I alloc the array at the beginning of imagePickerController method? Sorry for the novice questions and thank you for all of your help - Henry F 2012-04-04 00:52
You shouldn't alloc it unless it returns nil from user defaults, or you risk overwriting your existing array - borrrden 2012-04-04 01:00
Awesome thank you so much. And just one more question, will this automatically remove the image from the UI? I have no idea how I would do that manually in my alertView method. Thanks again for explaining everything, it is tremendously helpful - Henry F 2012-04-04 01:04
No, you have to do both every time. setting the image view's image to nil will be fine - borrrden 2012-04-04 01:09
Sweet thanks again. I've been trying to figure out how to set the image views image to nil for an hour or so. I figured that it would be alertView.tag.image = nil;, but that is obviously causing an error. I really need to go buy an Objective-C book, the books I've previously read do not cover any of this lol - Henry F 2012-04-04 02:46
Well, that is off topic for this question, unfortunately, so let's avoid making this comment list gigantic - borrrden 2012-04-04 02:48


3

Removing the image from the array is not the only step you have to take. Your code is correct for removing the image from the array, which is why you get image out of bounds the second time, but you also need to remove the image from the UI so the user can no longer delete an image that is not there.

2012-04-03 23:51
by Joe
Ah okay that makes sense, thank you. How would I go about removing the image from the UI? Sorry for the novice questions - Henry F 2012-04-04 02:36