Question

I am working through an iOS book and I've been extending an example program for practice when I stumbled into a issue I don't understand completely.

I'm currently working with a UINavigationController that has a rootView, a detailView and a third level view that I intend to turn into a modal view controller.

Everything is working as expected. My rootViewController is a UITableView that allows a user to select a row. The row will open a detailViewController for the given object that displays:

  1. Item Title
  2. Item Serial Number
  3. Item Value
  4. Purchase Date

On this DetailViewController there is a "Change Purchase Date" button that presents another ViewController to select a new date:
enter image description hereenter image description here

After Selecting a date and hitting the "Set Purchase Date" button I have the viewWillDisappear method save the changes to the Item Object in the third ViewController and then pop a view off the stack to return to the DetailViewController:
FILE: PurchaseDateViewController.m:

- (void) viewDidDisappear:(BOOL)animated {

    [super viewWillDisappear:animated];

    // Clear first responder
    [[self view] endEditing:YES];

    // "Save" the changes made to the creationDate
    [_item setDateCreated:[purchaseDatePicker date]];

    /* Debugging Log */
    // Create a NSDateFormatter that will turn the date into a simple string
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    [dateFormatter setTimeStyle:NSDateFormatterNoStyle];

    // NSLogging
    NSLog(@"Original Date: %@", [dateFormatter stringFromDate:_itemsOldDate]);
    NSLog(@"DatePicker Date: %@", [dateFormatter stringFromDate:[purchaseDatePicker date]]);
    NSLog(@"Stored Date: %@", [dateFormatter stringFromDate:[_item dateCreated]]);

    // Reload the DetailViewController to update the changes if the NavigationController is used to return to the DetailViewController


}

#pragma mark Action Methods to Update the Data Source
- (IBAction)setPurchaseDate:(id)sender {

    // "Save" the changes made to the creationDate
    [_item setDateCreated:[purchaseDatePicker date]];

    // Move back 1 level on the NavigationController Stack
    [[self navigationController] popViewControllerAnimated:YES];

}

- (void)cancelChange {

    // "Reset" the changes made to the creationDate
    [_item setDateCreated:_itemsOldDate];

    // Move back 1 level on the NavigationController Stack
    [[self navigationController] popViewControllerAnimated:YES];

}

All of the methods listed above work.

When using the "Set Purchase Date" button and PurchaseDateViewController is popped off the stack, the DetailViewController is updated immediately.

However, when I press the NavigationController back button, the view is NOT updated and the old date remains present on the DetailViewController. What's really weird is that the Item Object has been updated behind the scenes as my NSLog statements proved. This makes me believe that for some reason -viewWillAppear is not being called again.

This is confirmed if I hit the NavigationController's back button again and reselect the same row. When I take this testing approach, the date is updated to new date when re-entering the DetailViewController from the rootViewController. Since the DetailViewController is removed from the NavigationController stack and then instantiated again (therefore calling the DetailViewController's viewWillAppear again) the change is made.

Why isn't the viewWillLoad method getting called in this case? How come the change is not present when using the UINavigationControls and is there a way to explicitly reload the view? What is the recommend approach to overcoming this problem?

While writing this post I did find a way to force the viewWillAppear method to get called, but I feel there must be a more 'standardized' approach to overcoming this issue. What would the best practice be?

Here is the 'cheat' that I used to get around the problem:

PurchaseDateViewController.m

- (void)navigationController:(UINavigationController *)navigationController  willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [viewController viewWillAppear:animated];
}

- (void) viewDidDisappear:(BOOL)animated {

    [super viewWillDisappear:animated];

    // Clear first responder
    [[self view] endEditing:YES];

    // "Save" the changes made to the creationDate
    [_item setDateCreated:[purchaseDatePicker date]];

    /* Debugging Log */
    // Create a NSDateFormatter that will turn the date into a simple string
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    [dateFormatter setTimeStyle:NSDateFormatterNoStyle];

    // NSLogging
    NSLog(@"Original Date: %@", [dateFormatter stringFromDate:_itemsOldDate]);
    NSLog(@"DatePicker Date: %@", [dateFormatter stringFromDate:[purchaseDatePicker date]]);
    NSLog(@"Stored Date: %@", [dateFormatter stringFromDate:[_item dateCreated]]);

    // Reload the DetailViewController to update the changes if the NavigationController is used to return to the DetailViewController
    [self navigationController:[self navigationController]  willShowViewController:_detailViewController animated:YES];


}
Was it helpful?

Solution

The will be giving you a problem:

- (void) viewDidDisappear:(BOOL)animated {

[super viewWillDisappear:animated];

Should be

- (void) viewWillDisappear:(BOOL)animated {

[super viewWillDisappear:animated];

Typo? Or does that fix things?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top