【问题标题】:Crash with rotating SearchDisplayController: [Object _existingView]: unrecognized selector sent to instance旋转 SearchDisplayController 崩溃:[Object _existingView]:发送到实例的无法识别的选择器
【发布时间】:2012-10-11 15:22:13
【问题描述】:

我已经看到了关于这个主题的各种问题,但从未找到一个好的答案。

我有一个使用 UITableViewController 并为其实例化 SearchDisplayController 的应用程序。

我从崩溃报告者那里收到随机崩溃,每次看起来都像

[Object _existingView]: unrecognized selector sent to instance

对象可以是任何东西,绝对没有规则,只是它始终是一个内部对象,而不是来自 App 代码的对象。

它可以影响不同版本的iOS,最高可达6.0。

看起来 SearchDisplayController 尚未被释放,并且正在向内部对象发送旋转消息(请参阅下面的崩溃报告)

真的很奇怪,上面的代码是我在所有项目类中实例化searchDisplayController的唯一地方。

如果我能够重现此问题,我将永远不会在这里发布任何内容,但不幸的是,我无法重现它,即使尝试浏览应用程序本身中的数十个 UITableViewController 并向模拟器发送内存警告.

如果有人以前确实遇到过这个问题,那可能会很有趣,也许我们可以就这个话题提供一个明确的答案(关于这个的几个帖子)

这就是 searchBar 和 SearchDisplayController 的创建方式:

UISearchBar *searchBar = [[[UISearchBar alloc] init] autorelease];
searchBar.barStyle = UIBarStyleBlack;
self.createdSearchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchDisplayController.searchResultsDelegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.delegate = self;
searchBar.frame = CGRectMake(0, 0, 0, 38);
self.tableView.tableHeaderView = searchBar;

在阅读了一些答案之后,我已经将 dealloc 方法升级为 nil 委托,即使它应该是一个薄弱环节。 这就是我在 dealloc 中解除分配的方式(抱歉,ARC 之前的代码,我仍然需要升级):

[[NSNotificationCenter defaultCenter] removeObserver:self];
fetchedResultsController.delegate = nil;
self.searchDisplayController.delegate = nil;
self.searchDisplayController.searchResultsDelegate = nil;
self.searchDisplayController.searchResultsDataSource = nil;
[createdSearchDisplayController release];

我仍然不确定 SearchDisplayController 是否已正确释放,即使我没有看到任何其他方法,因为 searchDisplayController 是只读属性。

使用 Instruments 使用泄漏跟踪我没有看到任何泄漏,但是当查看那里的分配跟踪时,系统似乎保留了对 searchDiplayController 的一些引用,即使在模拟器中发送了多个内存警告之后也是如此。

在崩溃报告下方,除了第一个语句 main 和 start 之外,没有提及我们的 App:

0 CoreFoundation 0x35b0b88f __exceptionPreprocess + 162
1 libobjc.A.dylib 0x3372f259 objc_exception_throw + 32
2 CoreFoundation 0x35b0ea9b -[NSObject doesNotRecognizeSelector:] + 174
3 CoreFoundation 0x35b0d915 ___forwarding___ + 300
4 CoreFoundation 0x35a68650 _CF_forwarding_prep_0 + 48
5 UIKit 0x334d4ebb -[UISearchDisplayController windowWillAnimateRotation:] + 126
6 Foundation 0x34f254ff __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 18
7 CoreFoundation 0x35ad7547 ___CFXNotificationPost_block_invoke_0 + 70
8 CoreFoundation 0x35a63097 _CFXNotificationPost + 1406
9 Foundation 0x34e993eb -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
10 UIKit 0x332efa57 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 3450
11 UIKit 0x33380fa7 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 46
12 UIKit 0x33380f37 -[UIWindow _setRotatableViewOrientation:duration:force:] + 70
13 UIKit 0x3324fa01 -[UIWindow _updateToInterfaceOrientation:duration:force:] + 108
14 UIKit 0x33236cff -[UIWindow _updateInterfaceOrientationFromDeviceOrientation:] + 162
15 UIKit 0x332500c7 -[UIWindow _updateInterfaceOrientationFromDeviceOrientationIfRotationEnabled:] + 74
16 Foundation 0x34f254ff __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 18
17 CoreFoundation 0x35ad7547 ___CFXNotificationPost_block_invoke_0 + 70
18 CoreFoundation 0x35a63097 _CFXNotificationPost + 1406
19 Foundation 0x34e993eb -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
20 UIKit 0x33210deb -[UIDevice setOrientation:animated:] + 214
21 UIKit 0x3320c16f -[UIApplication handleEvent:withNewEvent:] + 2718
22 UIKit 0x3320b567 -[UIApplication sendEvent:] + 54
23 UIKit 0x3320af3b _UIApplicationHandleEvent + 5826
24 GraphicsServices 0x337fd22b PurpleEventCallback + 882
25 CoreFoundation 0x35adf523 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 38
26 CoreFoundation 0x35adf4c5 __CFRunLoopDoSource1 + 140
27 CoreFoundation 0x35ade313 __CFRunLoopRun + 1370
28 CoreFoundation 0x35a614a5 CFRunLoopRunSpecific + 300
29 CoreFoundation 0x35a6136d CFRunLoopRunInMode + 104
30 GraphicsServices 0x337fc439 GSEventRunModal + 136
31 UIKit 0x33239cd5 UIApplicationMain + 1080  
32 AppName 0x0001a1cb main + 66
33 AppName 0x00016348 start + 40

【问题讨论】:

    标签: ios rotation uisearchdisplaycontroller searchdisplaycontroller


    【解决方案1】:

    上面的代码肯定会泄漏,但是以一种微妙的方式。 您看不到仪器中的泄漏,但如果您跟踪堆中的分配,您会看到它们不断堆积。

    不知何故,我对 SO 的问题给了我关于解除分配问题的答案。

    Apple 在创建 searchDisplayController 时有一个非常奇怪的行为,他们将其设为只读属性,更令人困惑的是我们的标准做法不起作用:

    // This is not possible and not correct.
    self.searchDisplayController = nil
    

    但这并不意味着您不能向他们发送版本!

    // This is the only correct way of releasing a searchDisplayController from a TableView
    [self.searchDisplayController release]
    

    这应该在两个地方调用:

    • 当然是在你的 dealloc 方法中。
    • 在创建 searchBar 和 SDC 的 alloc 方法中。

    因此,创建 searchDisplayController 的正确且真正无泄漏的方法是:

    // Alloc and create searchBar + searchDisplayController
    if (self.searchDisplayController) [self.searchDisplayController release];
    UISearchBar *searchBar = [[[UISearchBar alloc] init] autorelease];
    searchBar.barStyle = UIBarStyleBlack;
    [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
    self.searchDisplayController.searchResultsDelegate = self;
    self.searchDisplayController.searchResultsDataSource = self;
    self.searchDisplayController.delegate = self;
    searchBar.frame = CGRectMake(0, 0, 0, 38);
    self.tableView.tableHeaderView = searchBar;
    
    // Dealloc
    [NSNotificationCenter defaultCenter] removeObserver:self];
    fetchedResultsController.delegate = nil;
    self.searchDisplayController.delegate = nil;
    self.searchDisplayController.searchResultsDelegate = nil;
    self.searchDisplayController.searchResultsDataSource = nil;
    [self.searchDisplayController release];
    

    在多次调用后,这已被验证为仪器中的堆增长 0。 并且已经在不同的 iOS 版本上进行了测试。 4.3 / 5.0 / 5.1 和 6.0

    目前,我仍然不确定它是否解决了旋转问题和对 _existingView 的无法识别调用,但它确实解决了正确解除分配 UITableViewController 中使用的 searchDisplayController 的问题。

    对论坛上一个从未得到正确回答的常规问题的回答。

    当然,我会在应用程序上线后更新崩溃问题(我们似乎无法重现该问题),看看它是否最终解决了它。

    【讨论】:

    • 更新版本已在商店上线 4 天。不再存在现有视图的问题。因此,不正确释放 SearchDisplay 控制器可能会导致旋转问题和意外崩溃。上述解决方案正在您的应用程序中创建和发布一个 searchDisplayController。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    • 2013-09-24
    相关资源
    最近更新 更多