核心数据委托方法被多次调用

Posted

技术标签:

【中文标题】核心数据委托方法被多次调用【英文标题】:core data delegate methods are getting called more than once 【发布时间】:2012-09-06 16:40:10 【问题描述】:

我正在使用 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]

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

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

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

以上是关于核心数据委托方法被多次调用的主要内容,如果未能解决你的问题,请参考以下文章

UIPickerView 委托和数据源方法没有被调用

核心动画立即调用完成函数

CALayer委托方法drawLayer没有被调用

UIPopoverController 委托委托方法未被调用

Facebook fbDidLogin 在 [facebook authorize:permissions] 之后被多次调用

哪个 UITextField 委托方法将被调用而无需重新设置键盘?