NSOperationQueue 避免将视图控制器推入导航控制器堆栈?

发布于 2024-11-09 06:36:23 字数 1214 浏览 4 评论 0原文

我有一个视图控制器,它是 UIViewController 的子类,其中包含表视图,并且表视图中的每一行都链接到不同的 xml url。 我创建了一个解析器类,它是 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];
}

解析器工作得很好,但在其自定义委托方法中,我调用了将视图控制器推送到导航控制器堆栈的顶部,视图控制器正确初始化,但新的视图控制器未推送到屏幕中。

我编辑了使用主线程和后台线程的问题,而后台线程可以正确解析主线程,只是初始化并且不会推送视图控制器。 问题是什么 ?

I have a view controller that is sub class of UIViewController which has table view into it and each rows in table view is linked to distinct xml url.
I made a parser class that is sub class of NSOperation and implemented methods to parse the XML file on selection of each row as,

- (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 works great but in its custom delegate method I have called to push view controller on the top of the navigation controller stack, the view controller initializes correctly but the new view controller is not pushed into the screen.

I have edited the question for using the main thread and background thread while the background thread works correctly for parsing the main thread just initializes and does not push view controller.
What is the problem ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你如我软肋 2024-11-16 06:36:23

您需要将视图控制器推送到主线程上。使用 performSelectorOnMainThread:withObject:waitUntilDone: 在主线程上调用方法。

如果您有可能推送多个视图控制器,则当一个视图控制器被推送到堆栈上而另一个视图控制器正在进行动画处理时,您的应用程序将会崩溃。在这种情况下,您应该指定 animated:NO,或者收集 NSArray 中的视图控制器并使用 setViewControllers:animated: 将它们添加到堆栈中。


回应您更新的问题:您不需要通过 performSelectorInBackground:withObject: 调用 parseOperation: 因为 NSOperationQueue 无论如何都会执行它在单独线程中创建的 NSOperation 。我建议向您的 NSOperation 子类添加一个 delegate 属性,并遵循以下模式:

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
}

You need to push the view controller(s) on the main thread. Use performSelectorOnMainThread:withObject:waitUntilDone: to invoke a method on the main thread.

If there is a possibility that you will push multiple view controllers, your app will crash if a view controller is pushed onto the stack while another is being animated in. In this case, you should either specify animated:NO, or collect the view controllers in an NSArray and use setViewControllers:animated: to add them to the stack.


In response to your updated question: You shouldn't need to call parseOperation: via performSelectorInBackground:withObject: since the NSOperationQueue will execute the NSOperation that it creates in a separate thread anyway. I suggest adding a delegate property to your NSOperation subclass and following this pattern:

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文