Cordova - window.history.back() not working on HTML back button in iOS 9
The problem is that setting of window.location.hash
is asynchronous in the iOS 9.0 UIWebview (used by Cordova/Phonegap) - see this bug report for details.
This causes issues when using jQuery Mobile which by default uses window.location.hash
to navigate between "pages". It also causes issues with popups/dialogs/select menus which use this mechanism.
You can fix this by preventing jQuery Mobile from automatically listening/using location.hash:
$(document).on("deviceready", function(){
$.mobile.hashListeningEnabled = false;
});
However, I found this had side effects on Android such as causing the hardware back button not to work, so I targeted it specifically at iOS 9 using cordova-plugin-device:
$(document).on("deviceready", function(){
if(device.platform === "iOS" && parseInt(device.version) === 9){
$.mobile.hashListeningEnabled = false;
}
});
Note that I'm using navigator.app.backHistory()
not window.history.back()
in conjunction with hashListeningEnabled = false
- this may make a difference.
Alternatively you can use this plugin to use the new WKWebView on iOS 8 and 9. WKWebView is used by Safari on iOS 8+, hence JQM sites viewed in the browser on iOS 9 don't encounter these issues. cordova-ios 3 still uses UIWebView due to a bug in WKWebView in iOS 8, but the upcoming cordova-ios 4 will support a WKWebView core plugin for iOS 9+. Note that there are additional considerations when using WKWebView with Cordova/Phonegap apps due to its stricter security, such as requiring CORS headers on XHR responses.
I think it is the A tag's default action causes the bug. So I just prevent the default action by adding return false
at end of the click handler function
And it works.
- html
<a id="back-btn">back</a>
javascript
$('#back-btn').on('click', function(e) { window.history.go(-1); return false; })
SOLUTION:
This line resolved my issue :
history.go(0);
I have replaced window.history.back()
with history.go(0);
Now it is working fine for me in iOS 9
In index.html
<script type="text/javascript">$.mobile.hashListeningEnabled = false;</script>
Add this in onDeviceReady function:
function onDeviceReady() {
if ( device.platform === "iOS" && parseInt( device.version ) === 9 ) {
$.mobile.hashListeningEnabled = false;
}
if ( !( $.mobile.hashListeningEnabled &&
$.mobile.path.isHashValid( location.hash ) &&
( $( hashPage ).is( ":jqmData(role='page')" ) ||
$.mobile.path.isPath( hash ) ||
hash === $.mobile.dialogHashKey ) ) ) {
// make sure to set initial popstate state if it exists
// so that navigation back to the initial page works properly
if ( $.event.special.navigate.isPushStateEnabled() ) {
$.mobile.navigate.navigator.squash( path.parseLocation().href );
}
$.mobile.changePage( $.mobile.firstPage, {
transition: "none",
reverse: true,
changeHash: false,
fromHashChange: true
} );
} else {
// trigger hashchange or navigate to squash and record the correct
// history entry for an initial hash path
if ( !$.event.special.navigate.isPushStateEnabled() ) {
$window.trigger( "hashchange", [true] );
} else {
// TODO figure out how to simplify this interaction with the initial history entry
// at the bottom js/navigate/navigate.js
$.mobile.navigate.history.stack = [];
$.mobile.navigate( $.mobile.path.isPath( location.hash ) ? location.hash : location.href );
}
}
}
Validation for device OS version (as history.go(0)
is working only with iOS 9) Prior to iOS 9 version window.history.back()
working perfectly
And now Add this piece of code in place of window.history.back()
if ( device.platform === "iOS" && parseInt( device.version ) === 9 ) {
console.log( "version" + device.version );
console.log( "iOS 9" );
history.go( 0 );
//write your code here
}
else {
window.history.back();
}
To fix this Message "Failed to load webpage with error: CDVWebViewDelegate: Navigation started when state=1" in console add below code in CDVWebViewDelegate.m
In - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
Method Comment this piece of code shown below:
/*if ([_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description};
NSError* error = [[NSError alloc] initWithDomain:@"CDVWebViewDelegate" code:1 userInfo:errorDictionary];
[_delegate webView:webView didFailLoadWithError:error];
}*/