17

StoryBoards を使用するプロジェクトがあり、ルート ビュー コントローラーに表示UISearchDisplayControllerされる のコンテキストで使用されます。UINavigationController新しいView Controllerをスタックにプッシュすると、シミュレートされたメモリ警告が発生します(または実際にメモリ不足の警告が表示されます)。前のビュー コントローラーは、そのビューを正常にアンロードします。ただし、スタックから 2 番目のビュー コントローラーをポップすると、EXC_BAD_ACCESS. NSZombies をオンにすると、次のことがわかりました。

[UISearchDisplayController 保持]: 割り当て解除されたインスタンス 0xb13aa30 に送信されたメッセージ

私は(少なくとも私のコードでは)そのメッセージをに送信していませんUISearchDisplayController。プログラム的に言えば、私はそれで何もしていません。ブレーク ポイントviewDidLoadは、最初のビュー コントローラーの にさえ入っていないことを示しています。

しかし、何か奇妙なことがあります: 笑いと笑いのためにretainviewDidLoad何が起こるかを確認するためだけに、クラッシュが発生しないことを確認するために、. ただし、私の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 のものの内部にあるようです。この問題を解消する方法についてのアイデアはありますか?

更新: View ControllerとSearch Display Controllerのプロパティ間の接続を削除しても、独自の接続を作成IBOutletしてもクラッシュします。おそらく悪いバグ?

更新 2:UISearchDisplayController (ストーリーボードではなく)の独自のインスタンスをプログラムで作成し、で作成するとviewDidLoad、すべてが想定どおりに機能します。

更新 3:ストーリーボードを使用した新しいプロジェクトで、この問題を一貫して再現できます。バニラのペン先を使って同じことをしたところ、すべてが想定どおりに機能しました。ただし、ストーリーボードとセグエを使用して同じものをセットアップすると、実際のプロジェクトと同じように爆発します。:(

RECAP : この問題を再現する手順は次のとおりです。

  1. ストーリーボードでView Controllerを作成しますUISearchDisplayController
  2. ナビゲーション スタックに新しいビュー コントローラーをプッシュする
  3. メモリ不足の警告を発生させる
  4. コントローラーをスタックからポップする
  5. カブーム!

viewDidLoadこの時点では、最初のビュー コントローラで呼び出されることさえありません。Apple のコードは、その前に爆発します。

4

7 に答える 7

13

これが私がしたことです(確かに、これは回避策であり、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;
于 2012-01-13T23:07:18.893 に答える
11

これまでのところ、ARC を使用した iOS 5 SDK の次の実用的なソリューションを見つけました。

.h ファイルで、独自の searchDisplayController プロパティを IBOutlet で宣言します

@property (strong, nonatomic) IBOutlet UISearchDisplayController * searchDisplayController;

次に、.m ファイルで合成します。

@synthesize searchDisplayController;

ただし、viewDidUnload で nil に設定しないでください。

検索ディスプレイ コントローラーが、継承されたプロパティを使用する代わりに、作成したプロパティを使用するようにします。

また、ジェスチャ認識エンジンにも同様のバグが発生することに気付きました (プログラムで作成するのではなく、ストーリーボードからジェスチャ認識エンジンを作成した場合)。また、STRONG ジェスチャ レコグナイザー プロパティを作成し、ストーリーボードで作成したジェスチャ レコグナイザー オブジェクトにフックする必要もあります。次に、viewDidUnload で、それらを nil に設定しないでください。<-- これにより、クラッシュが防止されます。

于 2012-05-24T09:35:00.797 に答える
0

self.searchDisplayController のみを使用しないのはなぜですか?

私はすでにそれを何度も使用していますが、問題は発生しません。必要に応じてカスタマイズすることもできます。

于 2012-01-14T12:47:39.253 に答える
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;
于 2014-04-16T16:21:20.120 に答える
0

@Wayne: ストーリーボードから作成された SearchDisplayController で同じ問題に遭遇し、コードが実行されていないときに発生したように見えるクラッシュをデバッグしようとして 1 日以上費やしました。私の場合、ユーザーが UITabBarController のタブをタップして、メモリ警告後にアンロードされた ViewController に戻るという症状がありました。アンロードされたView ControllerのviewDidLoadメソッドは決して実行されず、アセンブリコードのどこかでクラッシュする前に 、コードは少なくともtabBarController:didSelectViewController:( viewDidLoadの後に実行する必要があります)まで取得します!

この回避策を投稿し、すべてのフォローアップに感謝します。小さな改善として、UIDisplayController のインスタンス化を、searchDisplayController プロパティの遅延読み込みアクセサー メソッドに移動します。実際の効果はごくわずかですが、見栄えが良くなります!

于 2012-03-27T19:57:24.627 に答える
-1

ViewDidUnload呼び出されるとは、アプリケーションでメモリ例外が発生したことを意味します。

最初にメモリの問題を修正してから、ディスプレイビューコントローラの問題を自動的に検索して解決します。

コードには何も問題がないように思われるため、メモリ例外が発生した場合は、次のように言ってユーザーの前の画面を表示することをお勧めします[self.navigationController popViewControllerAnimated:NO]

于 2012-01-16T10:48:20.383 に答える