【问题标题】:UIWebView inside a UIScrollViewUIScrollView 内的 UIWebView
【发布时间】:2012-07-16 08:17:24
【问题描述】:

我的应用程序在 UIScrollView 中有多个 UIWebView 视图。有时我有 html 内容,所以我使用 UIWebView loadHTMLString:baseURL: 方法加载 UIWebView。这似乎不会导致问题。最近我开始使用 loadRequest: 方法加载一些带有 url 的 UIWebView 实例。一旦我开始这样做,每当我滚动时,我都会收到以下错误:

* 由于未捕获的异常 'CALayerInvalidGeometry' 导致应用程序终止,原因:'CALayer position contains NaN: [nan nan]'

使用以下堆栈跟踪:

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 的 sn-p

- (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 的滚动和用户输入。

我的第二个问题:当我明确禁用该功能时,为什么 UIWebView(或者至少是它的一个或多个子视图)处理滚动?

我的第三个问题:既然它似乎无论如何都在处理滚动,有没有其他方法可以拦截或禁用发送到 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,此解决方案将不起作用。

有什么建议吗?

【问题讨论】:

  • 您是否获得了有关此问题的更多信息?
  • 您是否尝试将 UIWebView 添加为另一个 UIScrollview 的子视图?您是否添加了子 WebView 来加载视频?我真的不明白你想要做什么!如果你能给我提供信息,也许我可以给你一些建议。
  • 我在我的项目中做了类似的事情,我想通过嵌入 UIWebView 来显示来自 youtube 频道的视频。

标签: ios uiwebview uiscrollview


【解决方案1】:

在尝试设置属性时检查 NaN 值:

BOOL isNaN = isnan(your_Value);

所以你可以正确处理这些值,一旦你有了这个并且你可以运行代码,首先找出为什么会发生这种情况会很好(我猜想在获得你尝试的值时会进行一些狡猾的计算设置)

另外,这里是 NaN 解释:http://en.wikipedia.org/wiki/NaN

【讨论】:

  • 要是这么简单就好了。唉,这实际上并没有回答我们的问题。计算无效偏移的是 webview,而不是外部滚动视图。它根据来自外部滚动视图的通知信息计算 NaN 值。在外部滚动视图上设置的值都很好。
【解决方案2】:

实际上,我只能建议尝试编写自己的“webview”类,该类将包含自定义 NSURLConnection 和 NSURLRequest 在后台,并使用 loadHTMLString 启动 WebView。我在应用程序中使用 WebView 时遇到了很多问题。所以 UIWebView loadRequest 调用可能没有解决方案。

【讨论】:

  • 你把我弄糊涂了。如何以及为什么?
【解决方案3】:

如果没有可使用的示例项目,很难调试它。所以我不确定是什么原因造成的。我会仔细检查你的框架计算。如果您的父 UIScrollView 在界面构建器中,我会尝试关闭自动布局以查看是否有区别(因为 contentSize 的工作方式不同)。

您还可以尝试其他一些方法:

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

这将确保您的父滚动视图将始终取代 web 视图。所以也许这会阻止错误发生。

根据您使用 Web 视图的方式,有一些情景替代方案:

  • 在 UIWebView 上调用 renderInContext 以获取屏幕截图并简单地使用 UIImage。处理 UIWebView 后,您实际上会使用更少的内存。

  • DTCoreText 允许您使用 CoreText 呈现某些 HTML 内容。

  • UIMarkupTextPrintFormatter 允许您“打印” HTML 内容。可以用来获取图片。

【讨论】:

  • 我知道没有示例项目很难调试。我很快就会发布一个示例项目。
【解决方案4】:

下面的代码可以禁用 webView 中的滚动。

webView.userInteractionEnabled = NO;

【讨论】:

  • @Luke 一开始我的英语不太好。我认为问题中的代码是 webView.scrollView.userInteractionEnabled 属性。我没有测试它。但是我的代码实际上禁用了 webView 的滚动功能.我制作了一个带有许多无法滚动的 webView 的滚动视图。它可以工作。
【解决方案5】:

您是否一直在 iOS 模拟器或实际设备上测试此代码?

我最近在模拟器中测试 iOS 5.1 时遇到了同样的崩溃,但在运行 5.1 的 iPad/iPhone 上没有遇到同样的崩溃。

iOS 6 在设备和模拟器上运行良好。

我认为这是由于 iOS 6 中的 UIWebView 更改,UIWebView 现在已更改为异步绘制其内容。

【讨论】:

    猜你喜欢
    • 2011-09-20
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 2011-01-11
    • 1970-01-01
    相关资源
    最近更新 更多