1

.navigationController popViewControllerAnimated:YESNSOperation屏幕未正确更新并使弹出视图可见但显然已解除分配的位置调用时,我遇到了一个奇怪的问题。

详细信息:我有一个访问本地sqlite数据库的列表视图。当点击一条记录时,它会显示该记录的详细视图并启动一个异步 NSOperation(在主线程上)以检查 XML 后端数据库以查看该记录在数据库中是否仍然可用。由于架构原因,我不会进入,我无法在列表视图上运行此操作,它必须在详细视图中。如果自上次同步后删除了记录,它会通知用户该记录已被删除,并popViewControllerAnimated在共享应用程序委托上调用。理想情况下,这将弹出当前详细视图并返回到先前的列表视图。

错误:正确的视图实际上已在内存中弹出(已被释放),但仍显示在屏幕上。导航栏是空白的,但我可以点击“返回”按钮应该在的位置,它会在列表视图之前导航到开始屏幕,这意味着至少导航栏知道它应该在哪里,甚至如果它没有正确显示标题或后退按钮。主要问题是详细视图仍然可见并且可以与之交互,这会导致应用程序崩溃。例如,详细视图还显示 a 中的数据UITableView,如果用户在表格中向下滚动,则会引发异常“-[xAccountDetailController tableView:cellForRowAtIndexPath:]:消息已发送到已释放实例”

这让我相信细节控制器已经被popViewControllerAnimated调用正确地释放了,但是如果表实际上调用了,那么显然有些东西仍然驻留在内存中cellForRowAtIndexPath,即使它的视图控制器已经从导航控制器中弹出。

在“详细信息”视图中手动按下后退按钮(对于未在后端删除的记录)效果很好。

解决方法尝试:当我向 NSOperation 传递对详细视图控制器的引用时,我试图popViewControllerAnimated直接从该视图的 navigationController 属性和共享应用程序委托调用。我还尝试弹出两个视图并将列表视图重新推送到 navigationController 上,但这会带来更令人不安的界面效果,其中根视图控制器和列表视图控制器似乎同时存在于导航栏中(标题相互覆盖而不是不存在)。我试图将 NSOperation 中存在的详细视图控制器的引用设置为 nil,但这没有任何作用。我尝试[detailView release]在弹出之前调用 a ,但正如预期的那样,它在弹出时失败,因为它在发布之前只有 1 的保留计数。我'popToViewController而且popToRootViewController似乎没有任何效果。旧视图始终存在,导航栏是唯一似乎可以做任何事情的界面元素,即使那样,它也显示不正确。我也尝试过重新加载表格,因为我真的不介意视图是否保持可见(没有弹出),我只想清除数据——但表格由于某种原因不会重新加载数据。

想法:由于运行 NSOperation 的 operationQueue 是相关详细视图的属性,因此我确保在详细视图的 dealloc 中取消所有操作并将对 operationQueue 的引用设置为 nil。我还尝试确保其他对象中对该视图的所有引用都设置为 nil。直接从详细视图上的按钮调用popViewControllerAnimated可以完美运行,所以一定是我从 NSOperation 调用该方法,在 NSOperationQueue 上运行,这是我想要弹出的详细视图的属性。某处的某些引用必须使该视图部分保持活动状态,但是当调用 pop 时,我似乎找不到任何仍在引用该视图的内容。

太多地方的代码太多了,无法在这里发布。

有什么想法吗?

抱歉问了这么长的问题,提前谢谢,

格雷格


编辑 1:我可以使用新的 UIViewController 在 NSOperation 之外轻松重现此问题。

在一种tableView:didSelectRowAtIndexPath方法中,我调用以下内容:

xBaseViewController * vc = [[xBaseViewController alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:vc animated:YES];
[vc performSelectorOnMainThread:@selector(popView) withObject:nil waitUntilDone:YES];

在vc中,popView方法:

[self.navigationController popViewControllerAnimated:YES];

我认为这与保留计数或 NSOperation 无关。以这种方式弹出视图,我在做一些根本错误的事情吗?

4

1 回答 1

2

您的问题是您试图在不是主线程的线程上刷新屏幕。在 iOS 中,您只能使用主线程更新屏幕上正在发生的事情。

你需要这样的代码:

[self performSelectorOnMainThread:@selector(mymethod) withObject:nil waitUntilDone:YES modes:nil];

它应该工作得很好。

于 2010-09-13T12:37:43.523 回答