Silver challenge : clear button


Hi folks

Here is my solution for the silver challenge :

  1. add a clear button in the .xib file
  2. ctrl-drag this button to the detailViewController.h to create an IBAction declaration
  3. implement the clearImage method

[code]- (IBAction)clearImage:(id)sender
if ([item imageKey]) {

// Remove the image from the screen
[imageView setImage:nil];

// Delete the image form the image store
[[BNRImageStore sharedStore] deleteImageForKey:[item imageKey]];

// Delete the imageKey of the item    
[item setImageKey:nil];
// Hide the clearImage button
[clearImageButton setHidden:YES];



I finally found out how to hide the button until it’s needed …
I declared it as a IBOutlet called clearImageButton in the xib file

And then I update the viewWillAppear: method like so:

[code] NSString *imageKey = [item imageKey];

if (imageKey) {
    // Get image for image key in the image store
    UIImage *imageToDisplay = [[BNRImageStore sharedStore] imageForKey];
    // Use that image to put on the screen in imageView
    [imageView setImage:imageToDisplay];
    // Show the clearImage button
    [clearImageButton setHidden:NO];
} else {
    // Clear the imageView
    [imageView setImage:nil];
    // Hide the clearImage button
    [clearImageButton setHidden:YES];[/code]



My clearImage function is the same as FreddyF except that instead of hiding the button, I disable it.

        //Disable the button
        [removeImageButton setEnabled:NO];

*Note - the “setHidden:” method is not part of the UIBarButtonItem based on the Intellisense and the documentation I looked up. (Please correct me if I am wrong)

I also took the challenge a step further and made sure that the button is disabled when there is no image present. Inside of “viewWillAppear:” I added the disable code when there was no image

    //Populate the imageView
    NSString *imageKey = [item imageKey];
    if (imageKey) {
        //Get the image for image key from image store
        UIImage *image = [[BNRImageStore sharedStore] imageForKey];
        //Use that image to put on the screen in the imageView
        [imageView setImage:image];
    else {
        //Clear the imageView. When the image is nil, the UIImageView won't display an image.
        [imageView setImage:nil];
        //Disable the button
        [removeImageButton setEnabled:NO];

Finally, at the end of “- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info” I enabled the remove image button after the image was selected and saved.

    //Put the image onto the screen in our image view
    [imageView setImage:image];
    //Take image picker off the screen - you must call this dismiss method
    [self dismissViewControllerAnimated:YES completion:nil];
    //Enable the Remove Image button
    [removeImageButton setEnabled:YES];


[quote]*Note - the “setHidden:” method is not part of the UIBarButtonItem based on the Intellisense and the documentation I looked up. (Please correct me if I am wrong)

True, it’s not a property of UIButton (my “clearImage” button is a simple UIButton).
But UIButton inherits from UIControl which inherits from UIView which does have a “hidden” property …

Why did I use “hidden” ?
I found out that, despite my efforts, I couldn’t disable the button when no image was present, even if I put

[clearImageButton setEnabled:NO];
at the end of viewWillAppear, as you did.
I probably missed something, and your solution is elegant !


I’ve decided to give this challenge a ‘twist’. Since I had no room for a ‘Clear’ Button, I decided to add a button in the toolbar (bottom of the screen, next to the button for taking pictures)

in DetailViewController.h I connected an outlet to the toolbar:

then I connected the RemoveImageButton to this action:

[code]- (IBAction)removeImage:(id)sender
NSString *key = [item imageKey];
if (key) //if there’s a key present, we also have an image
//so remove it from the store
[[BNRImageStore sharedStore] deleteImageForKey:key];
//and remove this key from the currently selected item
[item setImageKey:nil];
//also remove the displayed image from imageView
[imageView setImage:nil];

    //since image is now removed, disable the Remove Image Button:
    UIBarButtonItem *removeImageButton = [[toolBar items] objectAtIndex:1];
    [removeImageButton setEnabled:NO];


and finally, to keep the button in a reasonably enabled (image present) / disabled (image absent) state, I edited the viewWillAppear method like this:

NSString *imageKey = [item imageKey]; if (imageKey) { //get image for imageKey from image store UIImage *imageToDisplay = [[BNRImageStore sharedStore] imageForKey]; //use that image to put on the screen in imageView [imageView setImage:imageToDisplay]; //and set the Remove Image Button to enabled: UIBarButtonItem *removeImageButton = [[toolBar items] objectAtIndex:1]; [removeImageButton setEnabled:YES]; } else { //clear the imageView [imageView setImage:nil]; //and set the Remove Image Button to disabled: UIBarButtonItem *removeImageButton = [[toolBar items] objectAtIndex:1]; [removeImageButton setEnabled:NO]; }

Any suggestions - corrections - optimizations are welcome!!! :slight_smile:


I like the above solutions, here’s mine, without the show/hide functionality of the delete-image button that MakisK and others did.

I decided that I wanted to use the toolbar that the camera button was on, but I wanted the “delete picture” button to be on the RHS rather than just next to the camera button. When you add a second toolbar button to the XIB file, it always just sits right next to any others that you have set.

Search on stackOverflow, and find that you can effectively configure an invisible toolbarbutton: a UIBarButtonItem of type UIBarButtonSystemItemFlexibleSpace. So I added two UIBarButtonItems to my XIB file, made the first one a UIBarButtonSystemItemFlexibleSpace, and set its title to be “Picture of Item” (via the Attributes Inspector), although it does nothing. I also widened this button so that my second UIBarButton would be placed at the right place, i.e. very close to the right hand edge of the toolbar on screen. I also changed this new second button so that it would display as the “trash” icon. This way, the result is a bottom toolbar that is laid out as follows:

Picture of Item

at the bottom of the DetailViewController. The “Picture of Item” is a button as well, so that if there were an index of buttons that I wanted to control, my third button - the trash button - would have an index number of 2.

With the “trash” toolbarbutton, I did the ctrl-drag thing in the XIB, to the DetailViewController.h file, to create an action called trashPicture, which I then coded (in DetailViewController.m) as:

- (IBAction)trashPicture:(id)sender { [[BNRImageStore sharedStore] deleteImageForKey:item.imageKey]; item.imageKey = nil; imageView.image = nil; // [self viewWillAppear]; // this line is made redundant by the above line }

My initial version of the trashPicture:() method was just the first line of the above, i.e. just the deleteImageForKey line, which worked in that the image was deleted, but it didn’t remove it from the screen. Then I added a [self viewWillAppear] call, which redrew the screen, this time without the image (since it had been deleted), but I prefer this mechanism, which just kills the image on screen (borrowed from MakisK).


it took only one button and 3 lines of code

[code]- (IBAction)borraImagen:(id)sender {

[imageView setImage:nil];
NSString *key = item.imageKey;
[[BNRImageStore sharedStore] deleteImageForKey:key];



The setHidden/setEnabled was the functionality I was looking for as I had the same desire to modify the challenge for such a functionality.

What I found about the two is that, setHidden makes the button totally disappear and the user cannot access the button. setEnabled does not hide the button, however the user is only able to access the button if setEnabled has been set to TRUE.

Unhiding or enabling the button again at the end of didFinishPickingMediaWithInfo seems to be redundant. ViewWillAppear seems to be called again so that the button is automatically unhidden/enabled again.


Instead of flexible space toolbar button item you can also use a fixed space toolbar button item, which is what I used in this case.