【问题标题】:core data delegate methods are getting called more than once核心数据委托方法被多次调用
【发布时间】:2026-01-16 11:55:01
【问题描述】:

我正在使用 XMPP 创建一个 FBChat。我为 coredata 和 fetchedResults 创建了单独的类。

核心数据类:

@implementation CoreDataClass

@synthesize managedObjectContext = __managedObjectContext;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;


- (NSManagedObjectContext *)managedObjectContext
{

    if (__managedObjectContext != nil)
    {
        return __managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        __managedObjectContext = [[NSManagedObjectContext alloc] init] ;
        [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return __managedObjectContext;
}


- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil)
    {
        return __managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Chat" withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return __managedObjectModel;
}


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }
    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSURL *storeURL = [[delegate applicationDocumentsDirectory] URLByAppendingPathComponent:@"FacebookChat.sqlite"];
    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];



    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
    {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return __persistentStoreCoordinator;
}
- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil)
    {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
        {
                       NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
    }
}

FetchedControlClass:

@implementation FetchedControllClass
@synthesize fetchedResultsController;

#pragma mark Fetched Results

- (NSFetchedResultsController *)fetchedResultsController
{
    CoreDataClass *coreDataObject=[[CoreDataClass alloc]init];

    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }


    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Conversation" inManagedObjectContext:coreDataObject.managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setFetchBatchSize:20];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"facebookName" ascending:YES];

    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];    
    [fetchRequest setSortDescriptors:sortDescriptors];
    [sortDescriptor release];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:coreDataObject.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"] ;
    [fetchRequest release];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;
    [aFetchedResultsController release];
    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    [coreDataObject release];
    return fetchedResultsController;
}    

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    AlertListVC *alertListObject=[[AlertListVC alloc]initWithNibName:@"AlertListVC" bundle:nil];

    [alertListObject.tableView beginUpdates];
    [alertListObject release];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    AlertListVC *alertListObject=[[AlertListVC alloc]initWithNibName:@"AlertListVC" bundle:nil];


    switch(type) {
        case NSFetchedResultsChangeInsert:
            [alertListObject.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [alertListObject.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
    [alertListObject release];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    AlertListVC *alertListObject=[[AlertListVC alloc]initWithNibName:@"AlertListVC" bundle:nil];

    UITableView *tableView = alertListObject.tableView;

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [alertListObject configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
    [alertListObject release];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    AlertListVC *alertListObject=[[AlertListVC alloc]initWithNibName:@"AlertListVC" bundle:nil];
    [alertListObject.tableView endUpdates]; 
    [alertListObject release];

}

我已经为 MainChatClass 中的两个类创建了对象,并将来自 coredata 的对话添加到 ConversationClass

Conversation *conversation = (Conversation *)[NSEntityDescription
                                                          insertNewObjectForEntityForName:@"Conversation"
                                                          inManagedObjectContext:coreDataClassObject.managedObjectContext];

我能够得到 fetchedResults 但是 问题是: Coredata 方法被调用了两次(所以文件创建了两次)。如果我选​​择朋友聊天,那么应用程序将崩溃。我使用僵尸来跟踪问题。它显示一些错误为 负责来电者: 1.[MainChatClass tableView:didSelectRowAtIndexPath] 2.[NSFetchedResultsController(私有方法)_managedObjectContextDidChange]

我尝试了很多次,但这些方法仍然出错。 如果有人对此有想法,请帮助我。 提前致谢

【问题讨论】:

    标签: ios5 core-data xmpp nsfetchedresultscontroller nsmanagedobjectcontext


    【解决方案1】:

    在每个 FRC 委托方法中,您创建一个新的 alertListObject。这是没有意义的。您必须将更新消息发送到您现有的表格视图。

    发生崩溃是因为 alertListObject.tableViewnil 用于新创建的视图控制器。

    【讨论】:

    • 感谢您的回答。我已将 fetch 控制器委托方法放入主类并解决了问题。
    • @Anand:我很高兴听到这个消息。如果我的回答有帮助,您应该通过单击答案左侧的复选标记“接受”它。