Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with Page Cache in iOS 5 Safari when navigating back / unload event not fired

tl;dr - Safari on iOS 5 is caching so hard, it is breaking my site.

I am struggling with the way the Safari browser in iOS 5 deals with back forward cache, which they call "Page Cache". The way it is described here explains the behavior very well.

Quite simply, the Page Cache makes it so when you leave a page we “pause” it and when you come back we press “play.”

This is causing problems throughout my site. When using the back button, most other browsers will show you the page in the state it was loaded. Not Safari on iOS 5, it shows you the page as you last left it. A simple example would be the disabling of a submit button. If I use Javascript to disable a submit button, then submit a form, when you click back the submit button will still be disabled. This has been an issue in other browsers, including the desktop version of Safari, but it is solved by setting the onload event handler to a blank function. I believe this tells the browser to invalidate the cache because something important could have happened in that function. This hack does not seem to work for Safari on iOS 5.

Below is the issue boiled down to the bare essentials. When you load test.html you will see the text "Original Text". When you click the link, that text will change to "Changed text - forwarding to next page", then in 3 seconds you will be forwarded to test2.html. All is good up to this point in all browsers. In all other browsers, when you click the back button, the text you will see is "Original Text", but on Safari for iOS 5 you will see "Changed text - forwarding to next page".

Any suggestions on how to deal with this?

This is a simple example

test.html

<script>
function changeText() {
    el = document.getElementById("text");
    el.innerHTML = "Changed text - forwarding to next page";
    setTimeout("forward()",3000);       
}
function forward() {
    document.location.href = "test2.html";
}
</script>
<div id="text">Original Text</div>
<a href="Javascript:changeText()">Click Here</a>
<script>
window.onunload = function(){};
</script>

test2.html

<div>Click back button</div>

This is a second example using a form post. This is a simple example of how my app is working. When you navigate back to formtest2.asp, you should see the posted form value and the div text should be original.

formtest.asp

<form method="post" action="formtest2.asp">
    Test: <input type="text" name="test"/>
    <input type="submit" value="Submit"/>
</form>

formtest2.asp

<script>
function changeText() {
    el = document.getElementById("text");
    el.innerHTML = "Changed text - forwarding to next page";
    setTimeout("forward()",3000);       
}
function forward() {
    document.location.href = "test2.html";
}
</script>

<%
Dim test
test = Request("test")
Response.Write("Test value: " & test & "<br />")
%>

<div id="text">Original Text</div>
<a href="Javascript:changeText()">Click Here</a>
<script>
window.onunload = function(){};
</script>

test2.html

<div>Click back button</div>
like image 867
Clarke Avatar asked Nov 03 '11 00:11

Clarke


People also ask

What is back forward cache?

Back/forward cache (or bfcache) is a browser optimization that enables instant back and forward navigation. It significantly improves the browsing experience for users—especially those with slower networks or devices.

How do I turn off Safari cache on my Iphone?

Select the “Advanced” tab and check the “Show Develop menu in menu bar” option. Close the Preferences window. If you don't have the Menu Bar enabled, select the settings gear, then choose “Show Menu Bar“. Select “Develop“ > “Disable Caches“.

How do I view Safari cache on Iphone?

To view the Site Cache Storage in Safari iOS, one needs to open the Settings on their iOS device and scroll down to Safari Browser. From there the users need to go to the advanced option and tap on Website Data to view the storage Details.


1 Answers

I was also looking for an answer to the same issue. Going back in iOS 5 does not execute any javascript and just leaves the page in the previous state it was when you left or were redirected.

Trying the weird "onunload" hack found in "Is there a cross-browser onload event when clicking the back button?" only worked for iOS 4, not iOS 5 which does not call the event as expected. Nickolay pointed out new functions on web-kit called "pageshow" and "pagehide" which are much more reliable than Giuseppe's example.

  1. You need the hack from this article: "Is there a cross-browser onload event when clicking the back button?" for this to work in iOS 4.
  2. Use this script which uses the new event to safely check if the page was loaded from cache and force a reload (avoiding URLs checks and local storage and also include iPods) for iOS 5:

    <body onunload="">
    ...
    <script type="text/javascript">
    if ((/iphone|ipod|ipad.*os 5/gi).test(navigator.appVersion)) {
      window.onpageshow = function(evt) {
        // If persisted then it is in the page cache, force a reload of the page.
        if (evt.persisted) {
          document.body.style.display = "none";
          location.reload();
        }
      };
    }
    </script>
    
like image 91
BrutalDev Avatar answered Oct 16 '22 22:10

BrutalDev