Cordova - window.history.back() not working on HTML back button in iOS 9
Asked Answered
D

6

7

In my application I am using window.history.back to navigate back to previous View

Declaration of back button

 <div class="back_icon"  id="verification_back_icon"><a href="#" data-rel="back"  data-transition="slidedown"><img src="images/back_btn.png" width="23"/></a></div>

Button action:

$( "#verification_back_icon" ).on( "click", function ( e ) {
    if ( checkDirtyVacation() ) {
        e.preventDefault();
        if ( backbtnAlt == false ) {
            backbtnAlt = true;
            confirm( "All data will be lost. Do you want to continue?",
                function ( r ) {
                    if ( r ) {
                        //onBackKeyDown();
                        clearVacationvalues();
                        window.history.back();//this is not working in iOS 9
                    } else {

                    }
                    backbtnAlt = false;
                } );
        }
    }
    else {
        e.preventDefault();
        if ( $( ".vaction_location" ).hasClass( "chkSelect" ) ) {
            $( ".vaction_location" ).removeClass( "chkSelect" );
            $( ".vaction_location" ).addClass( "chkUnSelect" );
        }


        window.history.back();
    }
} );

This worked perfectly till iOS 8.4. In iOS 9 this navigation is not working.

I am using Apache Cordova native platform version 3.8.0 .

If anyone facing the similar problem please suggest me. I have tried with history.back doesn't work on iOS using Cordova, but no luck

Thank you.

Durrell answered 24/9, 2015 at 12:22 Comment(4)
If your "previous view" uses hashes, then your problem is probably due to the fact that setting of window.location.hash is asynchronous is iOS 9 UIWebView - see here. Hard to know without more details of what framework(s) you are using...Subfusc
@Subfusc ..thank you for response..Please see my updated questionDurrell
From your html snippet, it looks you may be using jQuery mobile? If so, what version? If not, give example of how you navigate between viewsSubfusc
Yes I am using Jquery mobile version: jQuery Mobile 1.4.5 @daveAldenDurrell
D
2

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];
}*/
Durrell answered 28/9, 2015 at 6:9 Comment(2)
Navigation is working fine , where as I am getting this line in Console: CDVWebViewDelegate: Navigation started when state=1 Failed to load webpage with error: CDVWebViewDelegate: Navigation started when state=1Durrell
Does any one know whether this behaviour is a minor or major issue?Durrell
S
7

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.

Subfusc answered 25/9, 2015 at 8:7 Comment(6)
after using $.mobile.hashListeningEnabled = false; in ondeviceReady method, the navigation click is not working. Earlier it popped back to loading page irrespective of forward navigation clicks count.Durrell
If that doesn't work, WKWebView may be a better optionSubfusc
Should I replace UIWebView with WKWebView in interface builder?I will try this once..Durrell
Don't know how your are building it (locally or cloud service), but yes try and see if WKWebView resolves the issues. If you go with WKWebView though be sure to do a good regression test as it may cause other issues.Subfusc
Do you know how to use WKWebView instead of UIWebview in mainViewController (here I am have it as - (void)webViewDidFinishLoad:(UIWebView*)theWebView )Durrell
Let us continue this discussion in chat.Durrell
P
4

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;
        })
    
Prokopyevsk answered 8/4, 2016 at 6:59 Comment(1)
I've tried multiple variations, this one worked for me. Simply adding a [return false;] did the job.Celia
D
2

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];
}*/
Durrell answered 28/9, 2015 at 6:9 Comment(2)
Navigation is working fine , where as I am getting this line in Console: CDVWebViewDelegate: Navigation started when state=1 Failed to load webpage with error: CDVWebViewDelegate: Navigation started when state=1Durrell
Does any one know whether this behaviour is a minor or major issue?Durrell
C
2

Disabling push state worked for me:

$.mobile.pushStateEnabled = false;

Crowe answered 12/10, 2015 at 18:12 Comment(2)
@lan Drake this is really working great unlike my solution .This is not giving any "navigation started when state =1 " issue..Thank you for the solution.Durrell
after disabling pushState by above way, could I use "navigator.app.backHistory()" for back ?Plasticizer
H
1

@Sujania,

According to the phonegap team, iOS9 is not officially support. This issue may be yet another bug in iOS9. You may have to wait for a fix.

PhoneGap Build iOS 9 Support Status
http://community.phonegap.com/nitobi/topics/phonegap-build-ios-9-support-status

Top line: iOS 9 is not officially supported until Cordova-iOS 4.0.0, which the Cordova team is hard at work on. However some issues can be solved with some simple configuration changes.

At this point in time, 4 bugs are reported to the Cordova Bug repository. Your issue does not appear in the respository - as of this date.

https://issues.apache.org/jira/browse/CB-9684?jql=text%20~%20%22iOS9%22

Housing answered 25/9, 2015 at 0:56 Comment(1)
Regardless, of what you are using, as the forum post states iOS 9 is not officially supported until Cordova-iOS 4.0.0. This means, create a work around, or wait until it is officially supported. OR file a bug report with cordova. OR wait until someone else creates a work around. For my part, I do not work on leading edge, so I am the wrong person to follow up with. --Best of Luck.Housing
P
0

Try this

if(r){
         try{
          var nav = window.navigator;
          if( this.phonegapNavigationEnabled && nav && nav.app && nav.app.backHistory )
          {
            nav.app.backHistory();
          }
          else 
          {
            window.history.back();
          }
        }
        catch(e)
        {
         alert(e);
        }
      }
Pirzada answered 24/9, 2015 at 12:32 Comment(1)
thank you for your response..But still the same issue ..My view does not pops back correctlyDurrell

© 2022 - 2024 — McMap. All rights reserved.