My application has several UIWebView views inside a UIScrollView. Sometimes I have html content, so I load the UIWebView using the UIWebView loadHTMLString: baseURL: method. This is not a problem. I recently started loading some instances of UIWebView using url using the loadRequest: method. As soon as I started to do this, each time I scroll, I get the following error:
* Application termination due to the uncaught exception "CALayerInvalidGeometry", reason: "CALayer position contains NaN: [nan nan] '
With the following stack trace:
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:] ()
I looked at a lot of questions and answers about this and realized that the apple scares it off, but I did not see the answers that provide an alternative.
My first question is: is there an alternative way to achieve the same effect?
Below is a snippet of how I create a 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)); } }
As you can see, I turned off scrolling and user input for UIWebView.
My second question is: why does the UIWebView (or at least one or more of its views) handle scrolling at all when I explicitly disabled this function?
My third question is: since it seems that scroll is still being processed anyway, is there any other way to intercept or disable the scroll notification that is sent to UIWebView?
As you can see, I really do not intend to let the user interact with the contents of the UIWebView - just let them view the contents.
In this case, an alternative would be to create a UIWebView outside of the UIScrollView that the user cannot see, capture its contents in an image and then display the contents in a UIImageView? If so, how would I capture the contents of a UIWebView into an image?
EDIT: I found a solution for this, which was pretty easy. Basically load your UIWebView, but don't add it as a subquery. When the UIWebView finishes loading, create the image using the code below:
- (void)webViewDidFinishLoad:(UIWebView *)webView{ UIGraphicsBeginImageContext(self.webContent.bounds.size); [self.webContent.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); [self.imageContent setImage:image]; }
It will still be interesting for me to hear answers to questions 1 through 3. In the future, if we decide to support interactive UIWebView, this solution will not work.
Any suggestions?