How to fix window.location issue in iOS9 UIWebview

user1751482 picture user1751482 · Sep 22, 2015 · Viewed 11.5k times · Source

Since iOS9 release, my web app does not work anymore. The application uses a url hash based navigation and route changes trigger in a unpredictable way since iOS9.

I made a lot of researches and find the issue in the managing of window.location in IOS9 UIWebview.

Related to this post, the angular community seems to have fixed the issue with a released patch for angular.js.

https://gist.github.com/IgorMinar/863acd413e3925bf282c

The issue has been identified as : The iOS9 UIWebview doesn't update the href synchronously while using window.location

I looked through their corrections for in IOS9 but I don't find a way to reproduce their correction to make it works with any (non angular) webapp.

https://github.com/angular/angular.js/commit/8d39bd8abf423517b5bff70137c2a29e32bff76d#otherHash https://github.com//petebacondarwin/angular.js/commit/47f16f35c213dbb165567102231ac1496246c456 https://github.com//angular/angular.js/blob/master/src/ng/browser.js

Does someone found or is working on a solution to make the angular solution work in any (non angular) web app?

Update:

This is the kind of link I'm calling

domain/player/index.html

then

domain/player/index.html#/online/presentation/ru1XA0nkvgHm/slide/0

with

[self.view stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.location.href = '#/offline/presentation/%@/slide/%ld?isNativeApp=1%@%@'",moduleId,(long)slideNumber,infoIcons,testingMode]]);

I made tests and found something strange.

If I make a double call with the last command, the second time, the hashchange event triggers.

I don't want to have to resubmit the app to the app store, I want to modify my html (that can be fetched from the server) to detect the hash change and make the app work.

Answer

Pete BD picture Pete BD · Sep 25, 2015

The problem is that this particular browser does not update the value for window.location.href until the next run of the JavaScript event loop. This means that if you write to that value then immediately read it back you get a different value:

console.log(window.location.href)   // -> http://my.domain.com/path/to/page
window.location.href = 'http://my.domain.com/path/to/other/page';
console.log(window.location.href)   // -> http://my.domain.com/path/to/page

// next tick of the event loop

console.log(window.location.href)   // -> http://my.domain.com/path/to/other/page

Notice that the second console.log returns the old value, not the new value. After the current event loop completes, the value is updated, as can be seen in the third console.log.

The fix that we have come up with, is to cache the value that we wrote, if the browser is not updating synchronously, and then to use that value from then on, instead of the value returned from window.location.href, until there is a hashchange event, which tells us that the browser has finally sorted itself out.

Here is a link to the commit in AngularJS where this is fixed: https://github.com/angular/angular.js/commit/8d39bd8abf423517b5bff70137c2a29e32bff76d