0

このトピックに関するさまざまな質問を見てきましたが、良い答えは見つかりませんでした。

UITableViewController を使用し、その SearchDisplayController をインスタンス化するアプリがあります。

クラッシュレポーターからランダムなクラッシュが発生し、毎回次のようになります

[Object _existingView]: unrecognized selector sent to instance

オブジェクトは何でもかまいません。絶対にルールはありませんが、アプリ コードからのものではなく、常に内部オブジェクトであることを除いてはありません。

6.0 までの異なるバージョンの iOS に影響を与える可能性があります。

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 が適切にリリースされているかどうかはまだわかりません。

インスツルメントの使用 リーク トレースを使用してもリークは見られませんが、割り当てトレースを確認すると、シミュレータでいくつかのメモリ警告を送信した後でも、システムが searchDiplayController への参照を保持しているようです。

クラッシュ レポートの下。最初のステートメント main と start を除いて、アプリについては言及されていません。

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
4

1 に答える 1

0

上記のコードは確実にリークしていますが、微妙な方法です。インストゥルメントのリークでは見られませんが、ヒープの割り当てを追跡すると、それらが積み重なっていくのがわかります。

どういうわけか、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]

これは、次の 2 か所で呼び出す必要があります。

  • もちろん、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];

これは、数回の呼び出しの後、instruments でヒープの成長が 0 であることが確認されています。また、さまざまな iOS バージョンでもテストされています。4.3 / 5.0 / 5.1 および 6.0

現時点では、ローテーションの問題と _existingView の認識されない呼び出しが解決されるかどうかはまだわかりませんが、UITableViewController で使用される searchDisplayController の割り当てを正しく解除するという問題は確実に修正されます。

正しく回答されなかったフォーラムの通常の質問への回答。

もちろん、アプリが修正されて公開されたら、クラッシュの問題について更新し (問題を再現できないようです)、最終的に解決したかどうかを確認します.

于 2012-10-13T10:06:23.470 に答える