iOS,Coredata:子类别的总和值在viewdidload上未准备就绪,并且此后未更新

iOS,Coredata:子类别的总和值在viewdidload上未准备就绪,并且此后未更新,ios,core-data,Ios,Core Data,我有一个基本的数据模型。主类别有几个子类别。在每个子类别中,您定义了每年预算的金额。所以我想: a) 每个主要类别的所有子类别支出的总和。 b) 作为总预算的所有主要类别支出的总和 然而,目前这还不起作用。我在viewWillExample方法中设置了textfield(因为我一直希望在再次打开视图时更新它)。第一次加载时,总和为0。切换到另一个视图并返回后,将显示正确的总和。之后,它不会自我更新。为什么呢 我是Coredata的新手。与我在这里执行的查询相比,获取属性可能是更好的方法吗?以下是

我有一个基本的数据模型。主类别有几个子类别。在每个子类别中,您定义了每年预算的金额。所以我想:

a) 每个主要类别的所有子类别支出的总和。 b) 作为总预算的所有主要类别支出的总和

然而,目前这还不起作用。我在viewWillExample方法中设置了textfield(因为我一直希望在再次打开视图时更新它)。第一次加载时,总和为0。切换到另一个视图并返回后,将显示正确的总和。之后,它不会自我更新。为什么呢

我是Coredata的新手。与我在这里执行的查询相比,获取属性可能是更好的方法吗?以下是相关的代码部分:

我的主视图控制器(此处显示所有主要类别的总预算):

数据库获取:

+ (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;
}
编辑: 以下是整个获取结果控制器设置方法:

- (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:&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];
    }
}
进一步编辑,整个获取结果控制器类:

@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:&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]) && (!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 <NSFetchedResultsSectionInfo>)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];
    }
}
@synthetic fetchedresultscoontroller=\u fetchedresultscoontroller;
@综合SuspendAutomaticTrackingOfchangesManagedObjectContext=\u SuspendAutomaticTrackingOfchangesManagedObjectContext;
@综合调试=_调试;
@合成起始更新=_起始更新;
@综合再排序=_再排序;
@综合tableView=\u tableView;
-(布尔)应自动旋转指针面定向:(UIInterfaceOrientation)interfaceOrientation
{
返回YES;
}
#pragma标记获取
-(空)穿孔
{
if(self.fetchedResultsController){
if(self.fetchedResultsController.fetchRequest.predicate){
if(self.debug)NSLog(@“[%@%@]获取%@带谓词:%@”、NSStringFromClass([self class])、NSStringFromSelector(_cmd)、self.fetchedResultsController.fetchRequest.entityName、self.fetchedResultsController.fetchRequest.predicate);
}否则{
if(self.debug)NSLog(@“[%@%@]获取所有%@(即,无谓词)”、NSStringFromClass([self class])、NSStringFromSelector(_cmd)、self.fetchedResultsController.fetchRequest.entityName);
}
n错误*错误;
[self.fetchedResultsController性能蚀刻:&错误];
如果(错误)NSLog(@“[%@%@]%@(%@)”、NSStringFromClass([self class])、NSStringFromSelector(_cmd)、[error localizedDescription]、[error localizedFailureReason]);
}否则{
如果(self.debug)NSLog(@“[%@%@]没有NSFetchedResultsController(尚未?)、NSStringFromClass([self class])、NSStringFromSelector(_cmd));
}
[self.tableView重载数据];
}
-(void)setFetchedResultsController:(NSFetchedResultsController*)新FRC
{
NSFetchedResultsController*oldfrc=\u fetchedResultsController;
如果(新FRC!=旧FRC){
_fetchedResultsController=newfrc;
newfrc.delegate=self;
if((!self.title | |[self.title IseQualtString:oldfrc.fetchRequest.entity.name])&&(!self.navigationController | |!self.navigationItem.title)){
self.title=newfrc.fetchRequest.entity.name;
}
国际单项体育联合会(新财务报告准则){
如果(self.debug)NSLog(@“[%@%@]@”、NSStringFromClass([self class])、NSStringFromSelector(_cmd)、oldfrc?@“更新”:“设置”);
[自执行蚀刻];
}否则{
如果(self.debug)NSLog(@“[%@%@]重置为nil”、NSStringFromClass([self class])、NSStringFromSelector(_cmd));
[self.tableView重载数据];
}
}
}
#pragma标记-UITableViewDataSource
-(NSInteger)表格视图中的节数:(UITableView*)表格视图
{
返回[[self.fetchedResultsController节]计数];
}
-(NSInteger)表视图:(UITableView*)表视图行数节:(NSInteger)节
{
返回[[[self.fetchedResultsController节]对象索引:节]numberOfObjects];
}
-(NSString*)表格视图:(UITableView*)表格视图标题标题标题部分:(NSInteger)部分
{
返回[[[self.fetchedResultsController节]对象索引:节]名称];
}
-(NSInteger)tableView:(UITableView*)分区索引的tableView部分exttitle:(NSString*)标题索引:(NSInteger)索引
{
return[self.fetchedResultsController sectionForSectionIndexTitle:title-atIndex:index];
}
-(NSArray*)sectionIndexTitlesForTableView:(UITableView*)表格视图
{
返回[self.fetchedResultsController节索引];
}
#pragma标记-NSFetchedResultsControllerDelegate
-(void)controllerWillChangeContent:(NSFetchedResultsController*)控制器
{
如果(!自我重新排序){
如果(!self.suspendAutomaticTrackingOffChangesManagedObjectContext){
[self.tableView开始更新];
self.beganUpdate=是;
}
}
}
-(void)控制器:(NSFetchedResultsController*)控制器
didChangeSection:(id)sectionInfo
atIndex:(整数)sectionIndex
forChangeType:(NSFetchedResultsChangeType)类型
{
如果(!自我重新排序){
如果(!self.suspendAutomaticTrackingOffChangesManagedObjectContext)
{
开关(类型)
{
案例NSFetchedResultsChangesInsert:
[self.tableView insertSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]带RowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]带RowAnimation:UITableViewRowAnimationFade];
打破
}
}
}
}
-(void)控制器:(NSFetchedResultsController*)控制器
didChangeObject:(id)一个对象
atIndexPath:(nsindepath*)indepath
forChangeType:(NSFetchedResultsChangeType)类型
newindepath:(nsindepath*)newindepath
{
如果(!自我重新排序){
如果(!self.suspendAutomaticTrackingOffChangesManagedObjectContext)
{
开关(类型)
{
案例NSFetchedResultsCh
@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:&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]) && (!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 <NSFetchedResultsSectionInfo>)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];
    }
}
- (void)displayData {
    //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];
}
-(void)useDocument
{
    if(![[NSFileManager defaultManager]fileExistsAtPath:[self.budgetDatabase.fileURL path]]){
        [self.budgetDatabase saveToURL:self.budgetDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            [self setupFetchedResultsController];
            [self displayData]; ******
            //[self initializeDatabaseWithData];
        }];
    } else if (self.budgetDatabase.documentState == UIDocumentStateClosed){
        [self.budgetDatabase openWithCompletionHandler:^(BOOL success){
            [self setupFetchedResultsController];
            [self displayData]; ******
        }];
    } else if (self.budgetDatabase.documentState == UIDocumentStateNormal){
        [self setupFetchedResultsController];
        [self displayData]; ******
    }
}