使用GCD从核心数据中获取数据会导致IOS问题

时间:2014-05-24 13:29:56

标签: ios grand-central-dispatch nsfetchrequest nsfetchedresultscontroller

您好我正在开发使用核心数据的IOS应用程序。在我的应用程序中,我使用拆分视图控制器。所以我的拆分视图控制器的主视图包含以下内容:

-(void) viewWillAppear:(BOOL)animated
{
[self getNotificationCounter];
    [self getTicketCounter];
}
-(void) getNotificationCounter:(UITableViewCell *) cell
{
dispatch_queue_t myQueue = dispatch_queue_create("My Notification Queue",NULL);
dispatch_async(myQueue, ^{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"NotificationsData" inManagedObjectContext:context];
    [fetchRequest setEntity:entity];
    NSError *error = nil;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];        dispatch_async(dispatch_get_main_queue(), ^{
       //update view;
    });
});
}

-(void) getTicketCounter:(UITableViewCell *) cell
{
dispatch_queue_t myQueue = dispatch_queue_create("My Ticket Queue",NULL);
dispatch_async(myQueue, ^{

    NSFetchRequest *ticketFetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *ticketEntity = [NSEntityDescription
                                         entityForName:@"Tickets" inManagedObjectContext:context];
    [ticketFetchRequest setEntity:ticketEntity];
    NSError *ticketError = nil;
    NSArray *ticketFetchedObjects = [context executeFetchRequest:ticketFetchRequest error:&ticketError];
       dispatch_async(dispatch_get_main_queue(), ^{
        // update view
       });
});
}

和详细视图控制器有以下内容。

- (NSFetchedResultsController *)fetchedResultsController {

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@“channels” inManagedObjectContext:context];
[fetchRequest setEntity:entity];

NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                          initWithKey:@"channelId" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:context sectionNameKeyPath:nil
                                               cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;

return _fetchedResultsController;
}

所以我的问题是这样的: 在我的详细视图控制器中,我有一个NSFetchRequestController,在主视图中有两个 两个带有两个GCD的NSFetchRequest。如果我以纵向模式启动我的应用程序,它的工作正常。但在横向模式下,它会停止而不会出现任何错误。另一件事如果从主控制器中删除一个GCD NSFetchRequest它工作正常或如果我删除NSFetechResultController然后它也可以正常工作。为什么会这样?难道我做错了什么。需要一些帮助。谢谢。

1 个答案:

答案 0 :(得分:2)

您不能让NSManagedObjectContextNSManagedObject交叉线程。

您必须为线程创建新的上下文。

dispatch_queue_t myQueue = dispatch_queue_create("My Ticket Queue",NULL);
dispatch_async(myQueue, ^{

NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] init];
threadContext.parent = context; //assumes other context is NSMainThreadConcurrencyType

    NSFetchRequest *ticketFetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *ticketEntity = [NSEntityDescription
                                         entityForName:@"Tickets" inManagedObjectContext:threadContext];
    [ticketFetchRequest setEntity:ticketEntity];
... 

要在上下文之间获取NSManagedObject,请使用objectID属性和[NSManagedObjectContext objectWithId:]

如果您进行编辑,则需要保存线程上下文。这些更改将自动传播到父上下文。

否则,您会像一张纸一样丢弃块末尾的上下文。

修改

此外,如果您想要的对象数量是唯一的,那么您可以使用 countForFetchRequest:error:上的NSManagedObjectContext

这将是一个更便宜的电话,因为没有为您创建对象。