UIWebView loading but not displaying content - ios

UIWebView successfully loaded content, but is not displaying it. UIWebView is just white screen. BUT, if you click on this UIWebView it will process your click. For example, if you click at place where the link should be (but in fact the white space), the click processed and next page loaded and displayed OK.
The bug is unstable. I got it only with local HTML file (our homepage, it generated locally), web content loads OK. It happens in 20% cases. But in the same time, it is very sticky. Once got white screen, you can reload this page many times and see white screen (but if you click on invisible link, another page displayed successfully). Sometimes it occasionally appears without any reason. Your can "scroll" this blank screen up and down and it occasionally loaded. This local HTML has a lot of stuff, embedded images, javascripts, etc, and it could be javascript problem, but I can't explain how it can be, that content invisible, but still clickable.
It happens in iPod real device and iPhone simulator 4.3, but can't reproduce it on iPad or iPad simulator.
I spent a whole day trying resolve this. Any ideas?

I solved this!
This really weird behaviour of UIWebView was caused by javascript code. The javascript was like (simplified):
<script>
function onLoad() {
location.href='xxx://pageLoaded';
}
</script>
<body onload='onLoad();'>
The idea of this code was to inform app about the fact that page was loaded. In the app I catch request to xxx://pageLoaded and cancel it (in shouldStartLoadWithRequest). Because request cancellation, I didn't expect any problems here. Espesially, I didn't expect that content will become invisible, but still clicable. I added timer (setTimeout) between onload fires and location.href change. It solves the problem.
NOTE: I know about webViewDidFinishLoad event in UIWebView. This is very simplified example just to explain the problem and the solution. Real javascript is more sophisticated and what it is doing can't be reached by simple use webViewDidFinishLoad.

Related

Embedded YouTube videos don't play on iPad (iOS 7) while HTML5 search input is visible

This is a bug that I have managed to fix by brute force, but I don't understand why the solution worked.
The problem was that embedded YouTube videos weren't working on a particular (responsive) site on iPad (tested in iOS7) in landscape view. I managed to narrow it down to a particular CSS rule that was showing a search input in the header when the browser was wide enough, so it would show in an iPad's landscape view but not in its portrait view.
After a little more brute force fiddling, I found that removing the type="search" from the input tag (which causes it to fall back to the default type="text") would fix the problem. None of my searches have come up with an explanation for why this works though, or even anyone else experiencing the same thing.
Some more details on the bug
The site works by showing an image at first, which would be replaced via JavaScript with the YouTube iframe when clicked. After this first click, it would autoplay on desktop browsers, and on the iPad it would load the video but wouldn't play until the user presses it again.
If the type="search" input was visible (display: block;), then tapping on the embedded video would not cause it to play; there would be no visible response to the tap. If I zoomed in and tapped on the controls at the top, like the name of the video, I could see them being underlined, and testing showed that there was no element covering the iframe and intercepting events.
Strangely, tapping on the very edge of the right hand side of the iframe would cause the video to start playing correctly. Otherwise, changing the iPad to portrait view (causing the search input to be hidden via CSS) would enable the iframe to be clicked in order to start the video playing. After that first click, all the video controls would work regardless of whether or not the search input was showing.
Just experienced this first-hand myself and wanted to add my kudos for you having written this up. Your SO question, even without an answer, pointed me in the right direction.
In my case it was nothing to do with Youtube. I had a page generated by Drupal in a large-ish site, in which the site-wide search mechanism used an auto-complete drupal module which had type="search" as the main input's type.
In IOS, users reported that Facebook, Twitter and Google Plus's respective "like" buttons all didn't work, along with a much larger angular app embedded in the page. They all used iframes and none of them seemed to respond to clicks.
Changing this seemingly innocuous, unrelated input's type from search to text solved this problem immediately.
Baffling.

Why Safari on iOS is not showing my HTML5 video poster?

I have this webpage:
http://healthpad.net/dashboard/
It have 10 <video> elements on it.
For some reason, when I load the page on an iPad, it is not showing the video posters.
Try the following:
load the page on a desktop browser
load it on an iPad or iPad simulator, and you get a big black box with a play button
please tell me why this is happening?
Here's what I've already ruled out:
Image Content-Type header.
I've validated that the image content-type header is properly set.
In the example above, the Content-Type header properly image/jpeg.
Interference with the video.js library
VideoJs is used to show that nice play button on desktop browsers and to customise the controls. This library doesn't interfere with the native player however.
Just to make sure, I've created a test video page which doesn't have the video-js class, so the library doesn't pick up and process that video. In fact, the test page doesn't even include any JS library, it's just
<html><body>
<video
controls
height="400"
width="600"
poster="http://healthpad.net/media/CACHE/images/uploads/video_poster_1414/bd5fba5a68ddd0f4b3f61193f6908962.jpg"
src="http://healthpad.net/media/uploads/video_processed_720p_1414.mp4"
></video>
</body></html>
http://healthpad.net/rj_templates/test/zzz/
Usage of any video attributes that may not be supported on Mobile Safari
The test page above just has a plain video tag. I've tried removing every other attribute except for src and poster, it didn't help.
Most of the StackOverflow questions on the topic just say "Restart your iPad"
Here's where it gets weird:
If you google around on this, the answers on StackOverflow that have been accepted often say "Restart your iPad, that did it for me".
So I've tried doing the same thing, at first I just said that it doesn't work in my case.
Then, I tried this:
(all of the following on the iPad simulator)
Go to the site, video posters don't show
Go to the test page (http://healthpad.net/rj_templates/test/zzz/), video poster doesn't show.
Click home to exit Safari (or Cmd+Shift+H mac shortcut for the simulator)
Double-Click home button to get the task switcher outside of Safari, tap and hold on the safari icon until the kill button shows.
Kill Safari
Open safari (restarted). At this point, if you load the test page (the one with just one video), the poster will show.
Now go to the multi-video page: (http://healthpad.net/dashboard/). Video posters don't show.
Go back to the single-video test page, the video poster for that one no longer works either.
Repeat steps 3 to 8 to see the process of when video posters stop working.
So apparently, at some point, Mobile Safari decides it will no longer show any video posters.
Also, apparently, my site triggers this condition.
Clarifications:
When posters no longer work, it doesn't only occur on one domain, no video posters will be loaded for any other site, regardless whether or not it's on a totally different domain (e.g. the demo video from http://www.videojs.com/).
In order to reset this behaviour, from what I've seen, you have to kill and restart Safari. Just closing and reopening it doesn't reset this state.
Does anyone have any idea why this is happening? Is there a way to work around it?
EDIT: looks like this no longer works. Not shocking given how much iOS has changed in the last 7 years.
I got this working by using a PNG instead of a JPG.
Weird thing is, the JPG worked in iOS Safari locally (via a POW server on local wifi) but when pushed to staging the poster image didn't load. Both the local and staging code were referencing the same file on S3.
Changed the file format to PNG and it loads fine.
I see the question keeps getting upvoted once in a while, though there's no answer.
So here's what I ended up doing:
On iOS, instead of showing the video player (even with autoload=false), I will just show the poster and a play button, two standalone <img> tags.
When they get clicked, I create the video player from javascript and tell it to play. Works fine, users don't see much difference.
I fixed it by adding preload="none" to my code.
<video width="344" preload="none" height="217" poster="/themes/custom/xxxxxx">
In Safari settings [iOS7] Block Pop-Ups turned "OFF" seemed to cure this for me, hope this helps.
Well if someone is still stuck on this is how I managed to get it done in React.js but the algorithm itself should be useful in any framework:
First I detect whether the browser is safari or not using the following in a useEffect:
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
then I set it inside a state object.
If safari is true then instead of displaying the video i simply display an image with that poster as its source. Then I have an onClick handler on the image tag itself clicking on it will change the above state back to false and hence image component will stop showing and video will be shown instead. Now one more problem you would have to tackle here is that on image click the image will disappear and video will appear and you'll then have to click the video again for it to play. That's bad UX. so for that you can simply attach a ref to the video and inside the click handler for Image after you set the state simple do :
videoRef.current.play()
This will start playing the video as well.
I know this is a hacky solution so don't come at me but it was the only thing i could do to get it work.

Strange UIWebView Bug/Behavior

We have a UIWebView in our app, displaying HTML data loaded from memory (not a file). We are experiencing some very strange bug/behavior. Some pages take very long time to render (1-2 minutes). We looked at the source of the pages, and it is indeed very busy with badly written CSS and HTML (not in our control). However, we noticed that if we set a webview to load a page, and then press the power button to shut the iPhone's screen, then immediately press the power button again, and go back to our app, the webview renders the page instantly.
Has anyone experienced this? Any ideas what's going on?
So, uhm, forgot to answer this. It ended up that some of our HTML data had images that were linking to internal organization URLs, which were not accessible outside. And since the web view did not ask the delegate whether it should load, we didn't know about those resources. Pressing the power button caused the connections to drop, which made it render the page.

Content disappears for fraction of a second on offline web app load

I've observed this on iOS 4.3 to 5.0. When you create a even a simple offline web app, meaning one HTML file + few assets such as CSS and JS (all present in the cache manifest), it works offline (I tested in Airplane Mode) – BUT, when you add such an app to your home screen and open it in fullscreen mode, it first displays initial content, then everything disappears (page becomes white) for half a second or more, then content reappears again.
You can see this by adding Glyphboard, a well-known and useful offline web app, to your iOS home screen and launching it a few times. You should see the white flash effect every time you load it.
This is a big problem because it gives away the non-nativeness of an app and gives the impression that the app is non-optimized for performance and buggy.
I've tried finding reports about this but all I can find is rumors and misconceptions about the iOS 4.3 JavaScript rendering engine fiasco, which doesn't need at all be related to this issue. But in iOS version 3 I distincly remember not ever seeing the white flash.
Clearing the screen and other artifacts while rendering is a common issue of HTML rendering due to the progressive nature of HTML. The concept is that the browser should draw as early and often as possible and render styles/scripts/content as they become available. It's possible the markup has an issue where all rendering is delayed until some content or a script is available. This could happen if:
You have dynamic heights based on image dimensions but you haven't
set the image dimensions in the markup or CSS.
Your layout is based on tables and you aren't using 'table-layout:fixed` in CSS.
Your HTML uses inline scripts with document.write().
You have some kind of onLoad() function that reveals/modifies content.
You link to an external stylesheet.
You're using uncacheable external content or you've disabled caching.
You're using external content that's returning 404 or isn't available offline.
Has your HTML/CSS changed between testing IOS versions?
I've found this to be caused by the use of:
<meta name="viewport" content="width=device-width initial-scale=1.0 maximum-scale=1.0 user-scalable=0">
With a minimal page, I get a white flash between the apple-touch-startup-image and the page contents if I use the viewport meta tag. If I take out the tag, no flash.
It's possible to work around the problem by setting the tag programatically.
I think what happens here is that iOS takes a screenshot from the page when it is added to the main menu. Then this screenshot is displayed during the application loads (WebKit loads). WebKit starts rendering the page and the page itself is constructed in such a way that the page content is not instantly available, leading to a white flash which is a rendered page when page content is not yet there,
You can avoid the problem to a certain level by building your JS/CSS so that it loads the initial HTML view fast and then lazily loads / builds the rest of the resources on the background. Also you can set a custom loading screen instead of the default screenshot iOS uses from the page.
Maybe if you can take yourself a screenshot of your app and then have something like this:
<body style="background: white url('my-initial-loading-screen.png')" />
... and make sure image is available and comes from manifest.
Or even better, have loading screen which does not require any external resources to show (just plain HTML) so you know the browser doesn't need to load anything.

Scrolling on iPad for an iframe within GWT window

PLEASE NOTE: This is not a "use two fingers to scroll" problem. Whether it is one finger, or two, or three, or the whole hand, for some reason our iframe does not scroll on an iPad. :)
Here is the scenario:
In our web application, which is built using EXT-GWT, we have a few windows that open as (maximized) pop-ups and present some forms to the users. These forms, which are most of the times external, are rendered in an iFrame and some of the forms have their content collapsed at the initial load - the user can choose to expand any section of the form, fill it in and submit. Now everything works fine except the scrolling in iPad. After the iframe's content is loaded and collapsed (collapsing is done using JS on the client side, basically, the content loads as expanded by default and then is collapsed by JS) iPad just fails to provide scolling to the iframe. Even after the content of the iframe is expanded the iframe does not get any scrolling.
As of now, we have solved this problem by increasing the height (using JavaScript) of the EXT-GWT window to the size of the expanded iframe body content. This makes the whole window scrollable, instead of just the iframe within the window. While it works, the window becomes way to big, so I was wondering if there is any better way for us to provide scrolling to the iframe.
Thanks for the help,
Nitin
For iOS devices you need set overflow: auto; or the scrolling won't work. For my web apps I used fancybox to display iframes modally and once I change the overflow setting in the css file the two finger scroll worked perfectly on the iPad.
After trying (almost) everything, I have come to the conclusion that increasing the GWT window height to the iframe.body.height is the only solution for getting the window/iframe to scroll on iPad. Hopefully, this will help someone in future.
I´m pretty new to GWT, but for me it worked like this:
The parent-div of the iframe has a class in my case, x-component.
I made an entry to my css file like this:
.x-component{-webkit-overflow-scrolling: touch; overflow:auto;}
It works as well if I set these entries not to the class, but to the div-element itself.
Hope that helps

Resources