我有一个项目使用StoryBoards和UISearchDisplayController
在UINavigationController
的上下文中使用,它出现在根视图控制器中。当我将一个新的视图控制器推入堆栈并导致模拟内存警告(或实际上得到一个低内存警告)。上一个视图控制器成功卸载其视图。但是,当我从堆栈中弹出第二个视图控制器时,我得到一个EXC_BAD_ACCESS
。我打开NSZombies并发现了这个:
[UISearchDisplayController retain]:发送到解除分配的实例0xb13aa30的消息
我不是(至少在我的代码中)将该消息发送到UISearchDisplayController
。用编程方式说,我没有做任何事情。断点显示我甚至没有进入第一个视图控制器的viewDidLoad
。
retain
中彻底viewDidLoad
SDC,只是为了看看会发生什么,不会发生崩溃。但是,我的UISearchDisplayController
实例是nil
。
我做了一个回溯并得到了这个输出:
#0 0x01e30e1e in ___forwarding___ ()
#1 0x01e30ce2 in __forwarding_prep_0___ ()
#2 0x01dd1490 in CFRetain ()
#3 0x01eb69c0 in +[__NSArrayI __new::] ()
#4 0x01e0a00a in -[__NSPlaceholderArray initWithObjects:count:] ()
#5 0x01e34f52 in +[NSArray arrayWithObjects:count:] ()
#6 0x01e5e084 in -[NSDictionary allValues] ()
#7 0x01035272 in -[UINib instantiateWithOwner:options:] ()
#8 0x00edce2c in -[UIViewController _loadViewFromNibNamed:bundle:] ()
#9 0x00edd3a9 in -[UIViewController loadView] ()
#10 0x00edd5cb in -[UIViewController view] ()
#11 0x00edd941 in -[UIViewController contentScrollView] ()
#12 0x00eef47d in -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] ()
#13 0x00eef66f in -[UINavigationController _layoutViewController:] ()
#14 0x00eef93b in -[UINavigationController _startTransition:fromViewController:toViewController:] ()
#15 0x00ef03df in -[UINavigationController _startDeferredTransitionIfNeeded] ()
#16 0x00ef16cb in _popViewControllerNormal ()
#17 0x00ef196c in -[UINavigationController _popViewControllerWithTransition:allowPoppingLast:] ()
#18 0x0b446e82 in -[UINavigationControllerAccessibility(SafeCategory) _popViewControllerWithTransition:allowPoppingLast:] ()
#19 0x00ef0b10 in -[UINavigationController popViewControllerAnimated:] ()
#20 0x00ef297d in -[UINavigationController navigationBar:shouldPopItem:] ()
#21 0x00e7dabe in -[UINavigationBar _popNavigationItemWithTransition:] ()
#22 0x00e7da49 in -[UINavigationBar popNavigationItemAnimated:] ()
#23 0x0b42208c in -[UINavigationBarAccessibility(SafeCategory) popNavigationItemAnimated:] ()
#24 0x00e80507 in -[UINavigationBar _handleMouseUpAtPoint:] ()
#25 0x00e8074c in -[UINavigationBar touchesEnded:withEvent:] ()
#26 0x00e3fa30 in -[UIWindow _sendTouchesForEvent:] ()
#27 0x00e3fc56 in -[UIWindow sendEvent:] ()
#28 0x00e26384 in -[UIApplication sendEvent:] ()
#29 0x00e19aa9 in _UIApplicationHandleEvent ()
#30 0x02d37fa9 in PurpleEventCallback ()
#31 0x01e9e1c5 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
#32 0x01e03022 in __CFRunLoopDoSource1 ()
#33 0x01e0190a in __CFRunLoopRun ()
#34 0x01e00db4 in CFRunLoopRunSpecific ()
#35 0x01e00ccb in CFRunLoopRunInMode ()
#36 0x02d36879 in GSEventRunModal ()
#37 0x02d3693e in GSEventRun ()
#38 0x00e17a9b in UIApplicationMain ()
#39 0x00002b72 in main (argc=1, argv=0xbffff620)
似乎没有任何真正有趣的东西(有吗?:P)并且似乎是Apple的所有内部结构。关于如何解决这个问题的任何想法?
更新:即使我删除了我的视图控制器与搜索显示控制器的属性之间的连接,但为它创建了自己的IBOutlet
,它仍然会崩溃。可能是坏虫?
更新2:当我以编程方式创建我自己的UISearchDisplayController
实例(不是通过故事板)并在viewDidLoad
中创建它时,一切都按照它的方式工作到。
更新3:我能够在带有故事板的新项目中始终如一地重现此问题。我使用香草笔尖做了同样的事情,一切都按照它想象的方式工作。但是,如果我使用故事板和segue设置相同的东西,它会像在我的真实项目中一样爆炸。 :(
RECAP :以下是重新创建此问题的步骤:
UISearchDisplayController
viewDidLoad
甚至没有在第一个视图控制器上被调用,Apple的代码在此之前就会爆炸。
答案 0 :(得分:12)
这是我做的(授予,这是一个解决方法,而不是修复Apple的错误):
首先,在基座UIViewController
中,我创建了一个名为searchController
的属性:
@property (nonatomic, retain) IBOutlet UISearchDisplayController* searchController;
我在通过界面构建器中添加了UISearchBar
,以便我在其UI中有一个占位符。然后,在我的viewDidLoad
我手动设置控制器并连接它:
UISearchDisplayController* searchController = [[UISearchDisplayController alloc]
initWithSearchBar:self.searchBar contentsController:self];
searchController.searchResultsDataSource = self;
searchController.searchResultsDelegate = self;
searchController.delegate = self;
self.searchController = searchController;
[searchController release];
在我的viewDidUnload
中,我一定要清除它:
self.searchController = nil;
答案 1 :(得分:11)
到目前为止,我发现这个使用ARC的iOS 5 SDK的解决方案:
<。>在.h文件中,使用IBOutlet 声明自己的searchDisplayController属性@property (strong, nonatomic) IBOutlet UISearchDisplayController * searchDisplayController;
然后在.m文件中,合成它:
@synthesize searchDisplayController;
但不在viewDidUnload中将其设置为nil。
这样搜索显示控制器将使用您创建的属性而不是使用继承的属性。
我还注意到手势识别器也会出现类似的错误(如果您从故事板创建手势识别器而不是以编程方式创建它们)。我们还需要创建STRONG手势识别器属性,并将它们与您在storyboard中创建的手势识别器对象挂钩。然后在viewDidUnload中,不要将它们设置为nil。 &lt; - 这可以防止崩溃。
答案 2 :(得分:0)
为什么不使用self.searchDisplayController?
我已经多次使用它不会造成任何问题。如果需要,您也可以自定义。
答案 3 :(得分:0)
@Wayne:我在使用Storyboard创建的SearchDisplayController遇到了同样的问题,花了一天时间尝试调试当我的代码都没有运行时似乎出现的崩溃。在我的情况下,症状是用户点击UITabBarController中的选项卡以返回到内存警告后已卸载的ViewController。卸载的视图控制器的viewDidLoad方法永远不会运行,代码至少就像tabBarController:didSelectViewController :(应该在 viewDidLoad之后运行)才能在汇编代码中崩溃之前崩溃!
非常感谢您发布此解决方法以及所有后续工作。一个小的改进是将您的UIDisplayController实例化移动到searchDisplayController属性的延迟加载的访问器方法。实际效果可以忽略不计,但看起来更好!
答案 4 :(得分:0)
需要注意的一点是,如果在searchDisplayController仍处于活动状态时离开视图,则可能会发生此类崩溃。这是我遇到的问题,在searchDisplayController中选择一个项目被设置为从堆栈中弹出视图控制器,为了解决这个问题,我必须在弹出视图之前包含以下代码...
if (self.searchDisplayController.active) {
[self.searchDisplayController setActive:NO];
}
答案 5 :(得分:0)
Explicitly declare your outlet
@property (nonatomic, strong) IBOutlet UISearchDisplayController *searchDisplayController;
Then in dealloc - add these lines - nil out the delegate / data source so that they do not receive any message further when the searchDisplayController deallocates itself.
self.searchDisplayController.delegate = nil;
self.searchDisplayController.searchResultsDelegate = nil;
self.searchDisplayController.searchResultsDataSource = nil;
答案 6 :(得分:-1)
ViewDidUnload调用意味着,您的应用程序中存在内存异常。
首先尝试修复你的内存问题,然后自动搜索显示视图控制器问题将得到解决。
因为代码中似乎没有任何问题,当发生内存异常时,最好通过说[self.navigationController popViewControllerAnimated:NO]