Challenge: Removing an Image


#1

Following is the code I used to implement the challenge but I can’t figure out why the last line of code: [self.view setNeedsDisplay]; does not cause the execution to reenter: - (void) viewWillAppear:(BOOL)animated.

[

  • (void) viewWillAppear:(BOOL)animated
    {
    [super viewWillAppear];

    [nameField setText:editingPossession.possessionName];
    [serialNumberField setText:editingPossession.serialNumber];
    [valueField setText:[NSString stringWithFormat:@"%d", editingPossession.valueInDollars]];

      //create a NSDateFormatter that will turn a date into a simple string
    

    NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc]init]autorelease];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
    [dateLabel setText:[dateFormatter stringFromDate:editingPossession.dateCreated]];
    self.navigationItem.title = editingPossession.possessionName;

    NSString *imageKey = editingPossession.imageKey;

    if (imageKey) {
    UIImage *imageToDisplay = [[ImageCache sharedImageCache] imageForKey];

      [imageView setImage:imageToDisplay];
      	// Add our custom add button as the nav bar's custom right view
      UIBarButtonItem *delButton = [[[UIBarButtonItem alloc] initWithTitle:(@"Delete Photo")
      															   style:UIBarButtonItemStyleBordered
      															  target:self
      															  action:@selector(delPhoto:)] autorelease];
      self.navigationItem.rightBarButtonItem = delButton;
      	}
    

    else {
    UIBarButtonItem *cameraBarButtonItem = [[[UIBarButtonItem alloc]
    initWithBarButtonSystemItem:UIBarButtonSystemItemCamera
    target:self
    action:@selector(takePicture:)]autorelease];
    //Place this image on our navigation bar when this view controller
    //is on top of the navigation stack
    [[self navigationItem] setRightBarButtonItem:cameraBarButtonItem];
    [imageView setImage:nil];
    }

}

  • (IBAction)delPhoto:(id)sender
    {
    [[ImageCache sharedImageCache] deleteImageForKey:[editingPossession imageKey]];
    [imageView setImage:nil];
    editingPossession.imageKey = nil;
    [self.view setNeedsDisplay];
    }

I can get the required behavior with:

  • (IBAction)delPhoto:(id)sender
    {
    [[ImageCache sharedImageCache] deleteImageForKey:[editingPossession imageKey]];
    editingPossession.imageKey = nil;
    UIBarButtonItem *cameraBarButtonItem = [[[UIBarButtonItem alloc]
    initWithBarButtonSystemItem:UIBarButtonSystemItemCamera
    target:self
    action:@selector(takePicture:)]autorelease];
    [[self navigationItem] setRightBarButtonItem:cameraBarButtonItem];
    [imageView setImage:nil];

}
but I am trying to understand why setNeedsDisplay doesn’t work.


#2

setNeedsDisplay only triggers the drawRect: method of a view object (not immediately, but after an event is handled).

viewWillAppear: is sent to a view controller when its view is moved on screen - examples of this are:

  1. When a navigation controller pushes a new view controller on the stack, that new view controller is sent viewWillAppear:
  2. When the user selects a tab from a tab bar controller, the selected view controller is sent viewWillAppear:
  3. When a view controller is set as the root view controller

Or any other time a view was not on screen and then goes on screen, viewWillAppear: is sent. setNeedsDisplay is for updating the content of a view.