Получение данных при многопоточности - PullRequest
0 голосов
/ 11 октября 2011

Я использую многопоточность при загрузке данных из базы данных.

Я делаю следующее

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
               ^{
                   // Get data
                   NSDate *pastDate = [CommonHelper getSelectedDateYearBackComponents:[NSDate date]];
                   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"users == %@ && startDate >= %@", objUser,pastDate];
                   NSMutableArray *fetchArray = [DataAccess searchObjectsInUserContext:@"userIngo" :predicate :@"startDate" :NO];

                   if ([fetchArray count] > 0)
                   {
                       dispatch_async(dispatch_get_main_queue(), 
                                     ^{
                                         // Reload table
                                         [self.tableView reloadData]; });
                   }

                   else 
                   {
                       dispatch_async(dispatch_get_main_queue(), 
                        ^{  // calling Webservice
                         });
                   }
                });

, где users - это объект, из которого я пытаюсь получить данные, а objUser - объект пользователя, для которого я получаю данные от пользователей.entity

, и мой код searchObjectsInUserContext выглядит следующим образом

+(NSMutableArray *) searchObjectsInLabContext: (NSString*) entityName : (NSPredicate *) predicate : (NSString*) sortKey : (BOOL) sortAscending
 {
i3EAppDelegate *appDelegate = (i3EAppDelegate *)[[UIApplication sharedApplication] delegate];

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setUndoManager:nil];
[context setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]];

// Register context with the notification center
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:context];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[request setEntity:entity]; 
[request setFetchBatchSize:10];
[request setReturnsObjectsAsFaults:NO];

// If a predicate was passed, pass it to the query
if(predicate != nil)
{
    [request setPredicate:predicate];
}

// If a sort key was passed, use it for sorting.
if(sortKey != nil)
{
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];
    [sortDescriptors release];
    [sortDescriptor release];
}

NSError *error;

NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];

if (mutableFetchResults == nil) {

    // Handle the error.
    // NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    exit(-1);  // Fail

}

[request release];
appDelegate = nil;

return [mutableFetchResults autorelease];
  }

Так что в моем searchObjectInUserContext я использую несколько managedObjectContext, чтобы он не создавал для меня проблем при многопоточности, как объяснил Фред Макканн в его сообщение в блоге .

Однако моя проблема в NSMutableArray *mutableFetchResults в моем searchObjectsInUserContext, потому что иногда он возвращает 0, даже если в базе данных есть данные.

Может кто-нибудь помочьменя с чем я не так делаю?

1 Ответ

2 голосов
/ 11 октября 2011
  1. Вы пропускаете контекст, который создаете; Вы никогда не выпускаете это.
  2. Нет необходимости регистрироваться в качестве наблюдателя, потому что вы никогда не сохраняете в этом контексте.
  3. Почему вы делаете изменчивую копию контекста? Это редко служит какой-либо полезной цели.
  4. Откуда вы знаете, что в базе данных есть данные?
  5. Этот метод запускается в фоновом потоке?

Обновление

В вашей доставке нет ничего плохого, поэтому я подозреваю, что проблема может быть связана с выбором времени. Эта выборка запускается до сохранения другого потока? Это объясняет поведение, которое вы видите.

Кроме того, почему вы запускаете это в фоновом потоке? Вы видите проблему с производительностью, которая требует фонового поиска, подобного этому?

Обновление 2

Во-первых, я все еще подвергаю сомнению необходимость фоновой загрузки. Обычно это зарезервировано для случаев, когда у вас проблемы с производительностью, поскольку выборка выполняется очень быстро.

Во-вторых, вы выбираете в фоновую очередь, но затем ничего не делаете с данными, которые вы выбрали. Вы не отдаете его на стол (что в любом случае было бы плохо), вы просто берете его и выбрасываете.

Если вы выбираете только для подсчета, не выбирайте, сделайте -[NSManagedObjectContext -countForFetchRequest: error:]. Это будет еще быстрее и избавит от необходимости фонового вызова очереди.

Если вы ожидаете что-то сделать с результатами, у вас есть проблема. Экземпляры NSManagedObject не могут пересечь границу потока / очереди. Таким образом, выборка в фоновой очереди делает очень мало для пользовательского интерфейса. Вам нужно для извлечения этих объектов из главной очереди / основного потока. В противном случае произойдет сбой, потому что Core Data не позволяет этого.

В конце концов ваши фоновые очереди приносят вам больше вреда, чем пользы, и они не решают проблему, которую вы пытаетесь решить.

...