8

私のアプリケーションには、UIScrollView内にいくつかのUIWebViewビューがあります。時々私はhtmlコンテンツを持っているので、UIWebViewをUIWebView loadHTMLString:baseURL:メソッドでロードします。これは問題を引き起こさないようです。最近、loadRequest:メソッドを使用してURLを使用してUIWebViewインスタンスの一部をロードし始めました。それを開始すると、スクロールするたびに次のエラーが発生します。

*キャッチされなかった例外「CALayerInvalidGeometry」が原因でアプリを終了しています。理由:「CALayerの位置にNaNが含まれています:[nannan]」

次のスタックトレースを使用します。

Thread 1, Queue : (null)
#0  0x01dd5caa in objc_exception_throw ()
#1  0x01f5da48 in +[NSException raise:format:arguments:] ()
#2  0x01f5d9b9 in +[NSException raise:format:] ()
#3  0x007e8c0d in CA::Layer::set_position(CA::Vec2<double> const&, bool) ()
#4  0x007def55 in -[CALayer setPosition:] ()
#5  0x037b07d3 in -[WebFixedPositionContent scrollOrZoomChanged:] ()
#6  0x00a5bfae in -[UIWebDocumentView _updateFixedPositionContent] ()
#7  0x00c66ff3 in -[UIWebBrowserView _updateFixedPositionContent] ()
#8  0x00a5b07e in -[UIWebDocumentView _didScroll] ()
#9  0x01fb6dea in -[NSObject performSelector:] ()
#10 0x01f207f1 in -[NSArray makeObjectsPerformSelector:] ()
#11 0x0091627d in -[UIScrollView(Static) _notifyDidScroll] ()
#12 0x009029ae in -[UIScrollView setContentOffset:] ()
#13 0x00909ac8 in -[UIScrollView _updatePanGesture] ()
#14 0x0090d3c0 in -[UIScrollView handlePan:] ()
#15 0x00b84e29 in _UIGestureRecognizerSendActions ()
#16 0x00b84133 in -[UIGestureRecognizer _updateGestureWithEvent:] ()
#17 0x00b853bf in -[UIGestureRecognizer _delayedUpdateGesture] ()
#18 0x00b87a21 in ___UIGestureRecognizerUpdate_block_invoke_0541 ()
#19 0x00b8797c in _UIGestureRecognizerApplyBlocksToArray ()
#20 0x00b803d7 in _UIGestureRecognizerUpdate ()
#21 0x008e51a2 in -[UIWindow _sendGesturesForEvent:] ()
#22 0x008e5532 in -[UIWindow sendEvent:] ()

私はこれに関する多くの質問と回答を見て、アップルがこれを思いとどまらせていることに気づきましたが、代替案を提供する回答は見当たりませんでした。

私の最初の質問:同じ効果を達成するための別の方法はありますか?

以下は、UIWebViewを作成する方法のスニペットです。

- (void) createWebView:(NSString*)url{
NSInteger requestedHeight = 480;
NSInteger requestedWidth = 640;

self.webContent = [[UIWebView alloc] initWithFrame: CGRectMake(0, self.frame.size.height, requestedWidth, requestedHeight)];
self.webContent.scrollView.userInteractionEnabled = NO;
self.webContent.scrollView.scrollEnabled = NO; 
self.webContent.scrollView.bounces = NO;

NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[self.webContent loadRequest:urlRequest];

[self addSubview:self.webContent];

NSInteger calculatedHeight = self.webContent.frame.origin.y + self.webContent.frame.size.height;
NSInteger calculatedWidth = self.webContent.frame.origin.x + self.webContent.frame.size.width;
if (calculatedHeight > self.frame.size.height || calculatedWidth > self.frame.size.width){
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, MAX(self.frame.size.width, calculatedWidth), MAX(self.frame.size.height, calculatedHeight + 5));
}    
}

ご覧のとおり、UIWebViewのスクロールとユーザー入力を無効にします。

2番目の質問:UIWebView(または少なくとも1つ以上のサブビュー)が、その機能を明示的に無効にしたときにスクロールを処理するのはなぜですか?

私の3番目の質問:とにかくスクロールを処理しているようですが、UIWebViewに送信されるスクロール通知を傍受または無効にする他の方法はありますか?

ご覧のとおり、私はユーザーがUIWebViewのコンテンツを操作できるようにするつもりはなく、コンテンツを表示できるようにするだけです。

このシナリオでは、UIScrollViewの外部にユーザーに表示されないUIWebViewを作成し、そのコンテンツを画像にキャプチャしてから、UIImageViewに表示するという代替案が考えられますか?もしそうなら、UIWebViewのコンテンツを画像にキャプチャするにはどうすればよいですか?

編集:私はこれに対する解決策を見つけました。それは非常に簡単でした。基本的にUIWebViewをロードしますが、サブビューとして追加しないでください。UIWebViewの読み込みが完了したら、次のコードで画像を作成します。

- (void)webViewDidFinishLoad:(UIWebView *)webView{
UIGraphicsBeginImageContext(self.webContent.bounds.size);
[self.webContent.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

[self.imageContent setImage:image];
}

質問1から3への回答を聞くことに興味があります。将来、インタラクティブなUIWebViewをサポートすることにした場合、このソリューションは機能しません。

助言がありますか?

4

5 に答える 5

2

このコードをiOSシミュレーターまたは実際のデバイスでテストしましたか?

最近、シミュレーターでiOS 5.1でテストしたときに同じクラッシュが発生しましたが、5.1を実行しているiPad/iPhoneでは同じクラッシュは発生しません。

iOS 6は、シミュレーターだけでなくデバイスでも正常に動作します。

これは、iOS 6でのUIWebViewの変更によるものと思われます。UIWebViewは、コンテンツを非同期で描画するように変更されました。

于 2013-02-21T20:10:55.547 に答える
1

次のコマンドでプロパティを設定する場合は、NaN値を確認してください。

BOOL isNaN = isnan(your_Value);

したがって、値を適切に処理できるようになります。これを取得してコードを実行できるようになったら、そもそもなぜこれが発生しているのかを調べるとよいでしょう(設定しようとしている値を取得するときに、やっかいな計算が行われると思います)。

また、ここに説明されているNaNがあります:http://en.wikipedia.org/wiki/NaN

于 2013-02-13T17:37:38.573 に答える
1

試してみるサンプルプロジェクトがなければ、これをデバッグするのは困難です。だから私はそれを引き起こしているのかわかりません。フレームの計算を再確認します。親のUIScrollViewがインターフェイスビルダーにある場合は、自動レイアウトをオフにして、違いが生じるかどうかを確認します(contentSizeの動作が異なるため)。

あなたが試すことができる他のいくつかのことがあります:

[webview.scrollView.panGestureRecognizer requireGestureRecognizerToFail:myScrollView.panGestureRecognizer];

これにより、親のスクロールビューが常にWebビューに取って代わります。したがって、おそらくそれはエラーがまったく起こらないようにするでしょう。

Webビューの使用方法に応じて、状況に応じた代替手段がいくつかあります。

  • UIWebViewでrenderInContextを呼び出してスクリーンショットを取得し、UIImageを使用するだけです。UIWebViewを破棄した後は、実際に使用するメモリが少なくなります。

  • DTCoreTextを使用すると、CoreTextを使用して特定のHTMLコンテンツをレンダリングできます。

  • UIMarkupTextPrintFormatterHTMLコンテンツを「印刷」できます。画像を取得するために使用できます。

于 2013-02-20T00:02:56.660 に答える
1

実際には、バックグラウンドでNSURLRequestを使用してカスタムNSURLConnectionを含み、loadHTMLStringを使用してWebViewを開始する独自の「webview」クラスを作成することのみをお勧めします。アプリケーションでWebViewを使用すると多くの問題が発生します。したがって、UIWebViewloadRequest呼び出しの解決策はありません。

于 2013-02-19T15:13:48.550 に答える
1

以下のコードは、webView のスクロールを無効にすることができます。

webView.userInteractionEnabled = NO;
于 2013-02-20T08:57:34.990 に答える