2010-05-03 59 views
11

我有两个视图控制器A和B从A,I导航以查看控制器B如下:UISearchDisplayController autorelease如何在不同的视图控制器中导致崩溃?

// 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 

} 

在BViewController,bPropery1与拷贝定义如下(注意属性,B还包含的UITableView和其他属性):

@property (nonatomic, copy) NSString *bProperty1; 

一切似乎导航来回A和B.这是直到我添加了一个UISearchDisplayController包含在BViewController表视图之间时正常工作。现在,当我从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 

NSZombies显示:

-[BViewController respondsToSelector:]: message sent to deallocated instance 0x406c1e0 

)和malloc(这段历史指向A的已公布的bViewController上面的navigateToB方法:

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 

有人可以p租约给我任何想法在这里发生了什么?在navigateToB方法中,一旦bViewController被释放(在pushViewController之后),那应该是bViewController。没有其他人甚至知道它,因为它位于navigateToB方法块的本地,并且已经发布。

当从B导航回A时,viewDillLoad,viewWillAppear等将不会再调用navigateToB。

它看起来像某种方式搜索显示控制器有一个引用我的AViewController中的东西,所以它是autoreleased它采取了这个“东西”与它,但我不明白这是如何可能的,特别是当我使用复制以在A和B之间传递数据。

我正在为此烦闷。我确信这是我的错误,所以我转向你,Stack Overflow传说任何智慧或建议如何解决这个问题。

很多谢谢。

回答

5

将视图控制器按到导航控制器上时,导航控制器将保留视图控制器。当视图控制器弹出时,导航控制器将释放它。

UISearchDisplayController似乎试图查看您的视图控制器是否响应选择器,因为它是从_destroyManagedTableView调用,我猜选择器是searchDisplayController:willUnloadSearchResultsTableView :(您的视图控制器是搜索显示控制器的委托,是正确的?)。

@robert - 该示例必须是错误的,因为pushViewController确实保留了它的参数。在页面上的所有其他示例或者在初始化后立即自动释放,或者在推送后释放。

+0

谢谢Brian。 BViewController是搜索显示控制器的委托,尽管malloc历史在跟踪中显示AViewController(我猜这是因为它显示了BViewController的起源?)。听起来像UISearchDisplayController试图发送它已经发布的代理?我是否需要以某种方式在BViewController的dealloc中释放/ nil UISearchDisplayController? – Tofrizer 2010-05-03 14:48:00

+1

是的,搜索显示控制器应该在BViewController的dealloc中释放(以及在BViewController的init中创建的或者由一个笔尖加载并分配给IBOutlet的其他任何东西)。 – Brian 2010-05-03 14:59:35

+3

谢谢,似乎在工作,你摇滚!我会继续测试和监控(当然,还会给你答案:)),但我现在看到发生了什么。顺便说一句,之所以我以前评论说:“我需要以某种方式”释放UISearchDisplayController是我从来没有创建一个搜索显示控制器的IBOutlet。最初在IB中,当我拖放新的UISearchDisplayController控件时,它似乎自动链接到文件所有者。现在我意识到,拥有一个明确的IBOutlet允许我发布搜索显示控制器及其委托视图控制器(BViewController)。 – Tofrizer 2010-05-03 15:23:03

32

我不得不通过增加这些线路到我的UITableViewController的dealloc方法那是UISearchDisplayController的代表解决了类似的问题:

self.searchDisplayController.delegate = nil; 
self.searchDisplayController.searchResultsDelegate = nil; 
self.searchDisplayController.searchResultsDataSource = nil; 

我有点被建议混淆起来,到搜索解决这个问题显示控制器应该释放dealloc - 你需要做的是删除指针,搜索显示控制器有你的表视图控制器,因为你的表视图控制器现在消失了,不应该在你的搜索显示控制器后来调用释放。它就像你想在dealloc中删除的其他委托引用一样。

+0

这对我有用。我以为我不需要这样做,因为我使用的是ARC,但是我将这些行添加到视图控制器的dealloc方法中,并使用搜索显示控制器,并且我像魅力一样工作!我不知道这是否是一个bug ... – cgossain 2013-07-08 21:35:00

+1

@cgossain这些属性是UISearchDisplayController中的“非原子,赋值”,因此,无效的引用将会破坏事物。恕我直言,我们需要向苹果提交一份RFE,以使其“非原子性,弱”。 – 2013-07-15 15:02:38

3

我有同样的问题。 searchDisplayController并没有在视图控制器的dealloc中被使用。相反,委托管理searchDisplayController的发布,这是在tableView发布之后完成的。 现在,在视图控制器的dealloc中手动输入此代码后,它现在工作正常。

self.searchDisplayController.delegate = nil; self.searchDisplayController.searchResultsDelegate = nil; self.searchDisplayController.searchResultsDataSource = nil;

感谢您的帮助。