UIWebView がクラッシュするのを防ぐ方法−2

追記:2012/5/11 どうもこれでもクラッシュすることがあるようです。真の原因が分かったら、どなたか、教えてください…
さらに追記しました:5/12 UIWebView がクラッシュするのを防ぐ方法-3 | Zero4Racer PRO Developer’s Blog

iOS5 で UIWebView を使用しているときはご注意-予期せぬクラッシュを防ぐ方法 | Zero4Racer PRO Developer’s Blog で基本的にとる方法として、delegateのリセット、removeFromSuperview、stopLoadingなどを上げたのですが、それでもうまくいきませんでした。理想的な方法ではないのですが、とりあえず落ちない(多分)ように修正したので報告しておきます。

WebViewの表示
WebViewの表示


落ちる典型のクラッシュログはこんな感じ

Incident Identifier: 4D932A22-85F0-4ED7-AAD5-8B9D77207992
CrashReporter Key: 92d191278ae2cc8971ec7375ba2d01242246f856
Hardware Model: iPad3,3
Process: TwitOverview [11240]
Path: /var/mobile/Applications/255B8BDB-8B16-4171-84D5-9F7DEC081A43/TwitOverview.app/TwitOverview
Identifier: TwitOverview
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]

Date/Time: 2012-05-03 15:30:35.606 -0700
OS Version: iPhone OS 5.1 (9B176)
Report Version: 104

Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000
Crashed Thread: 3


Thread 3 name: WebThread
Thread 3 Crashed:
0 libicucore.A.dylib 0x346f868c 0x34689000 + 456332
1 libicucore.A.dylib 0x34690f8c utext_setNativeIndex + 84
2 libicucore.A.dylib 0x34690f2e icu::RuleBasedBreakIterator::first() + 30
3 libicucore.A.dylib 0x34690e7c icu::RuleBasedBreakIterator::setText(UText*, UErrorCode&) + 116
4 libicucore.A.dylib 0x34690df8 ubrk_setText + 72
5 WebCore 0x332d4de4 WebCore::characterBreakIterator(unsigned short const*, int) + 84
6 WebKit 0x3248974a -[NSString(WebStringDrawing) __web_drawInRect:withFont:ellipsis:alignment:letterSpacing:lineSpacing:includeEmoji:truncationRect:measureOnly:renderedStringOut:drawUnderline:] + 1182
7 WebKit 0x32402078 -[NSString(WebStringDrawing) __web_drawInRect:withFont:ellipsis:alignment:letterSpacing:lineSpacing:includeEmoji:truncationRect:measureOnly:renderedStringOut:] + 108
8 WebKit 0x32401ffc -[NSString(WebStringDrawing) __web_drawInRect:withFont:ellipsis:alignment:letterSpacing:lineSpacing:includeEmoji:truncationRect:measureOnly:] + 100
9 WebKit 0x32401f88 -[NSString(WebStringDrawing) _web_drawInRect:withFont:ellipsis:alignment:lineSpacing:includeEmoji:truncationRect:measureOnly:] + 100
10 WebKit 0x32401f14 -[NSString(WebStringDrawing) _web_sizeInRect:withFont:ellipsis:lineSpacing:] + 80
11 UIKit 0x325cc804 -[NSString(UIStringDrawing) sizeWithFont:constrainedToSize:lineBreakMode:lineSpacing:] + 108
12 UIKit 0x32740f92 -[NSString(UIStringDrawing) sizeWithFont:constrainedToSize:lineBreakMode:] + 46
13 TwitOverview 0x000fe590 +[TOVTweetView calcApproxHeightWithWidth:tweetData:] (TOVTweetView.m:74)
14 TwitOverview 0x000fecb4 -[TOVTweetView layoutSubviews] (TOVTweetView.m:115)
15 UIKit 0x325a80d8 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 176
16 CoreFoundation 0x3197a1f4 -[NSObject performSelector:withObject:] + 36
17 QuartzCore 0x309f1a9e -[CALayer layoutSublayers] + 210
18 QuartzCore 0x309f16b6 CA::Layer::layout_if_needed(CA::Transaction*) + 210
19 QuartzCore 0x309f583c CA::Context::commit_transaction(CA::Transaction*) + 220
20 QuartzCore 0x309f5578 CA::Transaction::commit() + 308
21 QuartzCore 0x309ed4b2 CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 50
22 CoreFoundation 0x319efb14 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 12
23 CoreFoundation 0x319edd50 __CFRunLoopDoObservers + 252
24 CoreFoundation 0x319ee0aa __CFRunLoopRun + 754
25 CoreFoundation 0x3197149e CFRunLoopRunSpecific + 294
26 CoreFoundation 0x31971366 CFRunLoopRunInMode + 98
27 WebCore 0x332850f0 _ZL12RunWebThreadPv + 396
28 libsystem_c.dylib 0x3114072e _pthread_start + 314
29 libsystem_c.dylib 0x311405e8 thread_start + 0

落ちたスレッドだけ強調表示していますが、どうも表示を終わらせて、ビューが消えているのにもかかわらず、表示しようとしているために起きているよう。理論的には

webView.delegate=nil;
[webView stopLoading];
[webView removeFromSuperview];

で良さそうなのですが、それではうまくいきませんでした。それでとった方法は、
WebViewを持っているviewControllerを再利用し、複数回使用する時に毎回生成しない
という方法です。

通常は、StoryBoardで、segueを使っていたため、ViewControllerは、Segueで自動作成、自動解放されていたのですが、これを、古典的な、
[self presentModalViewController:detail animated:NO];

に変更して、UIStoryboardから、viewControllerを生成

if (!detail) {
UIStoryboard *story=[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
detail = [story instantiateViewControllerWithIdentifier:@"TOVTweetDetailViewController"];
}
 [self presentModalViewController:detail animated:NO];

これで、detailは、いつ度作成されたものが使い回されます。再利用するために,描画の初期化関係を少し調整。
これで、今のところUIWebView周りで落ちない様になっているみたいです。

StoryBoardについては、来月発売iOS5プログラミングブックで、詳しく解説されています!この部分は、藤川さん Hiroyuki-Fujikawa.HD (cqa02303) on Twitter 担当!凄くいいです。

クラッシュ対策、うまくいくといいですが。。。

「UIWebView がクラッシュするのを防ぐ方法−2」への2件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください