Is History API broken on iOS? (Location bar doesn't update on pushState) Is History API broken on iOS? (Location bar doesn't update on pushState) ios ios

Is History API broken on iOS? (Location bar doesn't update on pushState)


So the bottom line is that iOS has added its own security around the history API, meaning that you can't use script to change the url. Only a user action can allow the history API to change the url - i.e. a click - as per Aral's example.

The workaround is to uses a hash (aka fragment identifier) on the url.

Instead of the history.pushState we'll just change the location:

var i = 0;var locationUpdateInterval = setInterval(function(){  window.location.hash = i;  i++;}, 1000);   

To capture the event either when something changes the that location in the iOS app or if they have permalink to a particular page/panel in your app:

// named function on purpose for laterfunction hashchange() {  var pageId = location.hash.substr(1); // drop the # symbol  // do something with pageId}window.onhashchange = hashchange;// onload - if there's a hash on the url, try to do something with itif (location.hash) hashchange();

It's pretty poor that we can't use the pushState/popState on iOS, but it's the same security as not being able to trigger fullscreen video unless the user initiates the action, which is the same as downloading video or audio content on iOS - you can't script it, the user must start it (somehow or another).

Just as a note about Android - the problems are pretty similar, so this (should) also work as a workaround for Android.

If you want desktop support, most browsers support onhashchange but, yep, you guessed, IE is lacking behind - so you can polyfill that bad boy in (though requires jQuery...): http://benalman.com/projects/jquery-hashchange-plugin/

Hope that helps.


Works fine for me when using: https://github.com/browserstate/history.js - this also fixes many other cross browser bugs with the HTML5 History API.

As of v1.7, here are the bugs it solves:

  • History.js solves the following browser bugs:
    • HTML5 Browsers
      • Chrome 8 sometimes does not contain the correct state data when traversing back to the initial state
      • Safari 5, Safari iOS 4 and Firefox 3 and 4 do not fire the onhashchange event when the page is loaded with a hash
      • Safari 5 and Safari iOS 4 do not fire the onpopstate event when the hash has changed unlike the other browsers
      • Safari 5 and Safari iOS 4 fail to return to the correct state once a hash is replaced by a replaceState call / bug report
      • Safari 5 and Safari iOS 4 sometimes fail to apply the state change under busy conditions / bug report
      • Google Chrome 8,9,10 and Firefox 4 prior to the RC will always fire onpopstate once the page has loaded / change recommendation
      • Safari iOS 4.0, 4.1, 4.2 have a working HTML5 History API - although the actual back buttons of the browsers do not work, therefore we treat them as HTML4 browsers
      • None of the HTML5 browsers actually utilise the title argument to the pushState and replaceState calls
    • HTML4 Browsers
      • Old browsers like MSIE 6,7 and Firefox 2 do not have a onhashchange event
      • MSIE 6 and 7 sometimes do not apply a hash even it was told to (requiring a second call to the apply function)
      • Non-Opera HTML4 browsers sometimes do not apply the hash when the hash is not urlencoded
    • All Browsers
      • State data and titles do not persist once the site is left and then returned (includes page refreshes)
      • State titles are never applied to the document.title


(Update: Just saw that Remy answered too – read his in-depth answer, above, instead.)

Remy provided a workaround for this issue on Twitter.

Basically, if you change the location.hash, the address in the location bar updates. However, this does create a separate entry in the history (which doesn't work for what I'm trying to achieve). The workaround I'm implementing is to use hash-bang URLs for iOS and regular ones for other platforms until the iOS bug is fixed. This is definitely not ideal and I hope that Mobile Safari on iOS will start behaving like Chrome, Firefox and Safari on desktop.