从屏幕未正确更新的.navigationController popViewControllerAnimated:YES
调用NSOperation
时出现了一个奇怪的问题,并且弹出的视图仍然可见但显然已取消分配。
详细信息:我有一个列表视图,可以访问本地sqlite
数据库。当点击记录时,它会显示该记录的详细信息视图并启动异步NSOperation(在主线程上)以检查XML后端数据库以查看该记录是否仍在数据库中可用。由于架构原因我不会进入,我无法在列表视图上运行此操作,它必须在详细视图中。如果自上次同步后删除了记录,则会通知用户该记录已被删除,并在共享应用程序委托上调用popViewControllerAnimated
。理想情况下,这会弹出当前的详细信息视图并返回上一个列表视图。
错误:正确的视图实际上已在内存中弹出(已取消分配)但仍显示在屏幕上。导航栏是空白的,但我可以点击“后退”按钮所在的位置,然后导航到列表视图之前的开始屏幕,这意味着至少导航栏可以理解它应该在哪里,甚至如果它没有正确显示标题或后退按钮。主要问题是详细信息视图仍然可见并且可以与之交互,这会导致应用程序崩溃。例如,详细信息视图还显示UITableView
中的数据,如果用户在表中向下滚动,则会抛出异常“-[xAccountDetailController tableView:cellForRowAtIndexPath:]:
消息发送到解除分配的实例”
这让我相信详细控制器已被popViewControllerAnimated
调用正确释放,但显然某些东西仍存在于内存中,如果该表实际调用cellForRowAtIndexPath
,即使它是视图控制器已经从navigationController中弹出。
在详细信息视图上手动按下后退按钮(对于未在后端删除的记录)可以正常工作。
解决方法尝试:当我向NSOperation传递对详细视图控制器的引用时,我试图直接从该视图的navigationController属性和共享应用程序委托中调用popViewControllerAnimated
。我还尝试弹出两个视图并将列表视图重新推送到navigationController,但这会产生更令人不安的界面效果,其中根视图控制器和列表视图控制器似乎同时存在于导航栏中(标题相互覆盖)而不是不存在)。我试图将对NSOperation中存在的详细视图控制器的引用设置为nil,但这没有做任何事情。我尝试在弹出之前调用[detailView release]
,但正如预期的那样,它在弹出时失败,因为它在发布之前只有一个保留计数为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无关。以这种方式弹出视图我做了一些根本性的错误吗?
答案 0 :(得分:2)
您的问题是您正在尝试刷新不是主线程的线程上的屏幕。在iOS中,您只能使用主线程更新屏幕上发生的情况。
您需要这样的代码:
[self performSelectorOnMainThread:@selector(mymethod) withObject:nil waitUntilDone:YES modes:nil];
它应该只是花花公子。