NSOperationQueue избегает нажатия контроллера представления в стек навигационного контроллера?

У меня есть контроллер представления, который является подклассом UIViewController, в котором есть табличное представление, и каждая строка в табличном представлении связана с отдельным URL-адресом xml. Я создал класс синтаксического анализатора, который является подклассом NSOperation, и реализовал методы для анализа файла XML при выборе каждой строки, как,

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    [self performSelectorOnMainThread:@selector(pushView) withObject:nil waitUntilDone:NO];
    [self performSelectorInBackground:@selector(parseOperation:) withObject:indexPath];
}

- (void)pushView {
    detailView = [[viewDetailsController alloc] initWithNibName:@"viewDetailsController" bundle:nil];
    [self.navigationController pushViewController:detailView animated:YES]; 
}

 - (void)parseOperation:(NSIndexPath *)indexPath {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    self.queue = [[NSOperationQueue alloc] init];
    parserClass *parser = [[parserClass alloc] initWithParseUrl:[[self.arrayOfUrls objectAtIndex:indexPath.row]delegate:self];
    [queue addOperation:parser];
    [parser release];
    [pool release];
}

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

Я отредактировал вопрос для использования основного потока и фонового потока, в то время как фоновый поток работает правильно для синтаксического анализа основного потока, который просто инициализируется и не нажимает контроллер представления. В чем проблема ?


person Sandeep    schedule 23.05.2011    source источник


Ответы (1)


Вам нужно нажать контроллер(ы) представления в основном потоке. Используйте performSelectorOnMainThread:withObject:waitUntilDone: для вызова метода в основном потоке.

Если существует вероятность того, что вы отправите несколько контроллеров представления, ваше приложение рухнет, если контроллер представления будет помещен в стек во время анимации другого. В этом случае вы должны либо указать animated:NO, либо собрать контроллеры представления в NSArray и используйте setViewControllers:animated:, чтобы добавить их в стек.


В ответ на ваш обновленный вопрос: вам не нужно вызывать parseOperation: через performSelectorInBackground:withObject:, поскольку NSOperationQueue все равно выполнит NSOperation, который он создает в отдельном потоке. Я предлагаю добавить свойство delegate в ваш подкласс NSOperation и следовать этому шаблону:

MyViewController.m:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyParseOperation *parseOp = ...
    parseOp.delegate = self;
    [myOperationQueue addOperation:parseOp];
}

// Called by MyParseOperation
- (void)operationCompletedWithXML:(XML *)parsedXML
{
    // Use parsedXML to create and configure a view controller
    MyCustomViewController *vc = ...

    // Animation is OK since only one view controller will be created
    [self.navigationController pushViewController:vc animated:YES];
}

MyParseOperation.m:

// Call this method once the XML has been parsed
- (void)finishUp
{
    // Invoke delegate method on the main thread
    [self.delegate performSelectorOnMainThread:@selector(operationCompletedWithXML:) withObject:self.parsedXML waitUntilDone:YES];

    // Perform additional cleanup as necessary
}
person titaniumdecoy    schedule 23.05.2011
comment
В этом случае вы должны иметь контроллер представления, который вы только что поместили в стек, для выполнения асинхронного запроса и синтаксического анализа XML. - person titaniumdecoy; 28.05.2011