UISearchDisplayController自动释放如何导致其他视图控制器崩溃?

Tof*_*zer 11 objective-c uiviewcontroller iphone-sdk-3.0

我有两个视图控制器A和B.从A,我导航到视图控制器B,如下所示:

// in View Controller A 
// navigateToB method

-(void) navigateToB {

BViewController *bViewController = 
[[BViewController alloc] initWithNibName: @"BView" bundle:nil];

bViewController.bProperty1 = SOME_STRING_CONSTANT;
bViewController.title = @"A TITLE OF A VC's CHOOSING"; 
[self.navigationController pushViewController: bViewController animated:YES];
[bViewController release]; //<----- releasing 0x406c1e0

}
Run Code Online (Sandbox Code Playgroud)

在BViewController中,属性bPropery1定义为如下复制(注意,B还包含UITableView和其他属性):

@property (nonatomic, copy) NSString *bProperty1;
Run Code Online (Sandbox Code Playgroud)

在A和B之间来回导航时,一切似乎都能正常工作.直到我在BViewController中包含的表视图中添加了一个UISearchDisplayController.现在,当我离开B,回到A时,应用程序崩溃了.

堆栈跟踪显示在崩溃时自动释放的搜索显示控制器的外观:

#0 0x009663a7 in ___forwarding___
#1 0x009426c2 in __forwarding_prep_0___
#2 0x018c8539 in -[UISearchDisplayController _destroyManagedTableView]
#3 0x018c8ea4 in -[UISearchDisplayController dealloc]
#4 0x00285ce5 in NSPopAutoreleasePool
Run Code Online (Sandbox Code Playgroud)

NSZombies显示:

-[BViewController respondsToSelector:]: message sent to deallocated instance 0x406c1e0
Run Code Online (Sandbox Code Playgroud)

而malloc的历史就指向已经在A的navigateToB方法中发布的bViewController:

    Call [2] [arg=132]: thread_a065e720 |start  ... <snip> 
..._sendActionsForEvents:withEvent:] | -[UIControl sendAction:to:forEvent:] | -
[UIApplication sendAction:to:from:forEvent:] | -[**AViewController navigateToB**] | 
+[NSObject alloc] | +[NSObject allocWithZone:] | _internal_class_createInstance | 
_internal_class_createInstanceFromZone | calloc | malloc_zone_calloc 
Run Code Online (Sandbox Code Playgroud)

有人可以给我任何关于这里发生的事情的想法吗?在navigateToB方法中,一旦bViewController被释放(在pushViewController之后),那应该是bViewController的.没有其他人知道它,因为它是navigateToB方法块的本地并且它已经被释放.

当从B导航回A时,在viewDidLoad,viewWillAppear等中将调用任何将重新进入navigateToB的内容.

它看起来像是某种方式搜索显示控制器在我的AViewController中有一些引用,因此它是自动释放的,它正在使用它的"东西",但我无法理解这是如何可能的,特别是当我使用副本传递数据时A和B之间

我会为此而烦恼.我确定这是我的错误所以我转向你,Stack Overflow传说任何关于如何解决这个问题的智慧或建议.

非常感谢.

小智 32

我通过将这些行添加到我的UITableViewController的dealloc方法来解决类似的问题,该方法是UISearchDisplayController的委托:

self.searchDisplayController.delegate = nil;
self.searchDisplayController.searchResultsDelegate = nil;
self.searchDisplayController.searchResultsDataSource = nil;
Run Code Online (Sandbox Code Playgroud)

我有点担心修复此问题的建议搜索显示控制器应该在dealloc中发布 - 您需要做的是删除搜索显示控制器对表视图控制器的指针,因为您的表视图控制器现在当你的搜索显示控制器稍后发布时,不应该离开.它就像你想要在dealloc中取消的任何其他委托引用一样.


Bri*_*ian 5

将视图控制器推入导航控制器时,导航控制器将保留视图控制器.当弹出该视图控制器时,导航控制器会释放它.

UISearchDisplayController似乎是想看看您的视图控制器响应一个选择,并且因为它是从_destroyManagedTableView打电话,我猜的选择是searchDisplayController:willUnloadSearchResultsTableView:(您的视图控制器是搜索显示控制器的委托,对吗?).

@robert - 这个例子一定是错的,因为pushViewController确实保留了它的参数.页面上的所有其他示例要么在init之后立即自动释放,要么在推送后释放.

  • 谢谢,似乎工作,你摇滚!我会继续测试和监控(当然会给你答案:)但我现在看到发生了什么.顺便说一下,我之前评论过"我需要以某种方式"发布UISearchDisplayController的原因是我从未为搜索显示控制器创建一个IBOutlet.最初,在我拖动/删除新的UISearchDisplayController控件的IB中,它似乎自动链接到文件所有者.现在我意识到,拥有一个明确的IBOutlet允许我释放搜索显示控制器及其委托视图控制器(BViewController). (3认同)