title: iOS, Coredata: Sum of subcategories value not ready on viewdidload and not updated thereafter
body: <p>I have a basic datamodel. A main category has several subcategories. In each subcategory you define an amount of money you're budgeting per year. So I want:</p>
  
  <p>a) the sum of all subcategory expenditures for each main category.
  b) the sum of all main category expenditures as a total budget</p>
  
  <p>However at the moment this doesn't work. I have the textfield set in the viewwillappear method (since I always wanted it to be updated whenever the view is opened again). At first load up the sum is 0. After switching to another view and back the correct sum is displayed. And afterwards it doesn't update itself. Why is that? </p>
  
  <p>And I'm new to Coredata. Is a fetched property maybe a better way compared to the query I'm doing here? Here are relevant code sections:</p>
  
  <p>My main view controller (here to display the total budget of all main categories):</p>
  
  <pre><code>- (void)viewWillAppear:(BOOL)animated
  {
      //Initialize database
      [super viewWillAppear:animated];
      if(!self.budgetDatabase){
          NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentationDirectory inDomains:NSUserDomainMask] lastObject];
          [url URLByAppendingPathComponent:@"BudgetDatabase"];
          self.budgetDatabase = [[UIManagedDocument alloc]initWithFileURL:url];
      }
  
      //Total cost/month will be fetched and formatted
      NSNumberFormatter *numberFormatter =[[NSNumberFormatter alloc] init];
      [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
  
      self.sumLabel.text = [[DatabaseFetches budgetPerMonthForManagedObjectContext:self.budgetDatabase.managedObjectContext] getLocalizedCurrencyString];
      [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
  }
  </code></pre>
  
  <p>Database Fetches:</p>
  
  <pre><code>+ (NSNumber *)budgetPerMonthForManagedObjectContext:(NSManagedObjectContext *)context
  {
      NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MainCategory"];
      NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"position" ascending:NO];
      request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
  
      NSArray *matches = [context executeFetchRequest:request error:nil];
      CostsPeriodically *totalCostPerMonth = [[CostsPeriodically alloc]init];
  
      for (MainCategory *mainCategory in matches) {
          for (SpendingCategory *category in mainCategory.hasSpendingCategories){
              [totalCostPerMonth addCosts:category.costPerYear];
          }
      }
  
      return totalCostPerMonth.sumPerMonth;
  }
  </code></pre>
  
  <p>EDIT:
  These are the whole Fetched Results Controller setup methods:</p>
  
  <pre><code>- (void)setupFetchedResultsController
  {
      NSError *error = nil;
      NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MainCategory"];
      request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"position" ascending:YES]];
      [self.budgetDatabase.managedObjectContext executeFetchRequest:request error:&amp;error];
  
      self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
                                                                         managedObjectContext:self.budgetDatabase.managedObjectContext
                                                                           sectionNameKeyPath:nil
                                                                                    cacheName:nil];
  }
  
  -(void)useDocument
  {
      if(![[NSFileManager defaultManager]fileExistsAtPath:[self.budgetDatabase.fileURL path]]){
          [self.budgetDatabase saveToURL:self.budgetDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
              [self setupFetchedResultsController];
              //[self initializeDatabaseWithData];
          }];
      } else if (self.budgetDatabase.documentState == UIDocumentStateClosed){
          [self.budgetDatabase openWithCompletionHandler:^(BOOL success){
              [self setupFetchedResultsController];
          }];
      } else if (self.budgetDatabase.documentState == UIDocumentStateNormal){
          [self setupFetchedResultsController];
      }
  }
  
  -(void)setBudgetDatabase:(UIManagedDocument *)budgetDatabase
  {
      if(_budgetDatabase != budgetDatabase){
          _budgetDatabase = budgetDatabase;
          [self useDocument];
      }
  }
  </code></pre>
  
  <p><strong>Further edit, whole Fetched results controller class:</strong></p>
  
  <pre><code>@synthesize fetchedResultsController = _fetchedResultsController;
  @synthesize suspendAutomaticTrackingOfChangesInManagedObjectContext = _suspendAutomaticTrackingOfChangesInManagedObjectContext;
  @synthesize debug = _debug;
  @synthesize beganUpdates = _beganUpdates;
  @synthesize reordering = _reordering;
  @synthesize tableView = _tableView;
  
  - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  {
      return YES;
  }
  
  #pragma mark - Fetching
  
  - (void)performFetch
  {
      if (self.fetchedResultsController) {
          if (self.fetchedResultsController.fetchRequest.predicate) {
              if (self.debug) NSLog(@"[%@ %@] fetching %@ with predicate: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName, self.fetchedResultsController.fetchRequest.predicate);
          } else {
              if (self.debug) NSLog(@"[%@ %@] fetching all %@ (i.e., no predicate)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName);
          }
          NSError *error;
          [self.fetchedResultsController performFetch:&amp;error];
          if (error) NSLog(@"[%@ %@] %@ (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]);
      } else {
          if (self.debug) NSLog(@"[%@ %@] no NSFetchedResultsController (yet?)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
      }
      [self.tableView reloadData];
  }
  
  - (void)setFetchedResultsController:(NSFetchedResultsController *)newfrc
  {
      NSFetchedResultsController *oldfrc = _fetchedResultsController;
      if (newfrc != oldfrc) {
          _fetchedResultsController = newfrc;
          newfrc.delegate = self;
          if ((!self.title || [self.title isEqualToString:oldfrc.fetchRequest.entity.name]) &amp;&amp; (!self.navigationController || !self.navigationItem.title)) {
              self.title = newfrc.fetchRequest.entity.name;
          }
          if (newfrc) {
              if (self.debug) NSLog(@"[%@ %@] %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), oldfrc ? @"updated" : @"set");
              [self performFetch];
          } else {
              if (self.debug) NSLog(@"[%@ %@] reset to nil", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
              [self.tableView reloadData];
          }
      }
  }
  
  #pragma mark - UITableViewDataSource
  
  - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
  {
      return [[self.fetchedResultsController sections] count];
  }
  
  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  {
      return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
  }
  
  - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
  {
      return [[[self.fetchedResultsController sections] objectAtIndex:section] name];
  }
  
  - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
  {
      return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
  }
  
  - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
  {
      return [self.fetchedResultsController sectionIndexTitles];
  }
  
  #pragma mark - NSFetchedResultsControllerDelegate
  
  - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
  {
      if(!self.reordering){
          if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) {
              [self.tableView beginUpdates];
              self.beganUpdates = YES;
          }
      }
  }
  
  - (void)controller:(NSFetchedResultsController *)controller
    didChangeSection:(id &lt;NSFetchedResultsSectionInfo&gt;)sectionInfo
             atIndex:(NSUInteger)sectionIndex
       forChangeType:(NSFetchedResultsChangeType)type
  {
      if(!self.reordering){
          if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
          {
              switch(type)
              {
                  case NSFetchedResultsChangeInsert:
                      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
                      break;
  
                  case NSFetchedResultsChangeDelete:
                      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
                      break;
              }
          }
      }
  }
  
  
  - (void)controller:(NSFetchedResultsController *)controller
     didChangeObject:(id)anObject
         atIndexPath:(NSIndexPath *)indexPath
       forChangeType:(NSFetchedResultsChangeType)type
        newIndexPath:(NSIndexPath *)newIndexPath
  {
      if(!self.reordering){
          if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
          {
              switch(type)
              {
                  case NSFetchedResultsChangeInsert:
                      [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                      break;
  
                  case NSFetchedResultsChangeDelete:
                      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                      break;
  
                  case NSFetchedResultsChangeUpdate:
                      [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                      break;
  
                  case NSFetchedResultsChangeMove:
                      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                      [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                      break;
              }
          }
      }
  }
  
  - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
  {
      if(!self.reordering){
          if (self.beganUpdates) [self.tableView endUpdates];
      }
  }
  
  - (void)endSuspensionOfUpdatesDueToContextChanges
  {
      _suspendAutomaticTrackingOfChangesInManagedObjectContext = NO;
  }
  
  - (void)setSuspendAutomaticTrackingOfChangesInManagedObjectContext:(BOOL)suspend
  {
      if (suspend) {
          _suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
      } else {
          [self performSelector:@selector(endSuspensionOfUpdatesDueToContextChanges) withObject:0 afterDelay:0];
      }
  }
  </code></pre>