首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSOperationQueue和UITableView版本正在破坏我的应用程序

NSOperationQueue和UITableView版本正在破坏我的应用程序
EN

Stack Overflow用户
提问于 2011-09-07 13:28:04
回答 2查看 881关注 0票数 0

到目前为止,这是我遇到的最奇怪的问题。

我在UINavigationController上有一个UINavigationController,我想使用NSInvocationOperation在viewDidAppear上调用一个方法,这样当视图变得可见时,它就可以在后台线程上运行。

问题是,如果我在操作(在本例中是testMethod方法)完成运行之前弹出视图控制器,那么应用程序就会崩溃。

如果我在操作完成后弹出视图控制器,一切都很好。

当应用程序崩溃时,它以"EXC-BAD-ACCESS“停止在超级dealloc,并给出以下错误。

bool _WebTryThreadLock(bool),xxxxxxxxx:尝试从主线程或web线程以外的线程获取web锁。这可能是从辅助线程调用UIKit的结果。现在崩溃..。

这是我的代码(超级简化)..

代码语言:javascript
复制
- (void)viewDidAppear:(BOOL)animated
{
     [super viewDidAppear:animated];

    NSInvocationOperation *theOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(testMethod) object:nil];
    [operationQueue addOperation:theOperation];
    [theOperation release];
}

- (void)testMethod
{
    NSLog(@"do some stuff that takes a few seconds to complete");
}

- (void)dealloc
{
    [_tableView release];
    [super dealloc];
}

testMethod有一些需要几秒钟才能完成的代码。我只有几条线索,我真的不知道如何从哪里开始调试。

  • 线索#1:最有趣的是,如果我从dealloc中删除_tableView发行版,那么应用程序就不会崩溃。当然,这会导致漏洞,而我无法删除它。viewDidLoad.
  • Clue
  • 线索2:我在一个单独的“干净”UIViewController上测试了这段代码,让我感到惊讶的是,它没有崩溃。
  • 线索3:应用程序没有崩溃是UITableView的数据源设置为0在UITableView#4中:如果我在viewDidAppear中使用与IBAction.
  • Clue #5相同的代码,应用程序就不会崩溃:我已经尝试过查看一下用NSZombie来堆叠数据,但是它给了我大量的数据,而且它没有给我带来任何线索。

我的UITableViewDelegate和UITableViewDataSource中有一些非常复杂的代码,我真的不知道从哪里开始调试它。我真的希望我不必一行行,也不要因为这个而重写整件事。

关于我该去哪找有什么建议?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-09-07 13:39:55

问题可能是您的视图控制器的最后一个引用是保存它的操作队列,这意味着当操作清除时,您在后台线程中调用(或让系统调用)一些UIKit方法(一个大的no)。

为了防止这种情况发生,您需要在操作结束时向主线程上的控制器发送一条保持活动的消息,方法是在testMethod的最后一行中添加类似的内容。

代码语言:javascript
复制
[self performSelectorOnMainThread:@selector(description) withObject:nil waitUntilDone:NO];

在操作队列释放视图控制器之前,仍然有可能对此消息进行处理,但这种可能性非常小。如果它还在发生,你可以这样做:

代码语言:javascript
复制
[self performSelectorOnMainThread:@selector(keepAlive:) 
                       withObject:[NSNumber numberWithBool:YES]
                    waitUntilDone:NO];

- (void)keepAlive:(NSNumber *)fromBackground
{
    if (fromBackground)
         [self performSelector:@selector(keepAlive:) withObject:nil afterDelay:1];
}

通过向主线程上的视图控制器发送消息,它将使对象保持活动状态(NSObject将保留视图控制器直到主线程处理该消息)。如果在延迟后执行选择器,它还将使视图控制器保持活动状态。

票数 2
EN

Stack Overflow用户

发布于 2011-09-07 13:56:41

您正在崩溃,因为控制器仍然试图使用您的tableView引用,并且由于您已弹出了viewController,所有东西都会在dealloc中消失,而tableView仍然在填充自己。您可以尝试在dealloc方法中询问您的操作是否仍在运行,因此您可以取消它,并且一切都应该很好。

一旦将操作添加到队列中,操作就无法控制。队列接管并处理该任务的调度。但是,如果您稍后决定不想执行操作--因为用户按了进度面板中的cancel按钮或退出应用程序--您可以取消操作,以防止它不必要地占用CPU时间。为此,您可以调用操作对象本身的cancel方法,或者调用NSOperationQueue类的NSOperationQueue方法。

取消操作并不会立即迫使它停止正在执行的操作。虽然所有操作都需要尊重isCancelled返回的值,但您的代码必须显式检查此方法返回的值,并根据需要中止。NSOperation的默认实现确实包括检查是否取消。例如,如果在调用开始方法之前取消操作,则开始方法退出而不启动任务。。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7334647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档