Cordova - 在iOS 9中,HTML返回按钮上的window.history.back()无法正常工作

7
在我的应用程序中,我使用 window.history.back 来返回到先前的视图。 返回按钮声明
 <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>
$( "#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();
    }
} );

这个在 iOS 8.4 之前完美运行。在 iOS 9 中,导航无法正常工作。
我正在使用 Apache Cordova 原生平台版本 3.8.0。
如果有人遇到类似的问题,请给我建议。 我已经尝试过 history.back doesn't work on iOS using Cordova,但没有成功。
谢谢。

如果您的“上一个视图”使用哈希,则问题可能由于在iOS 9 UIWebView中设置window.location.hash是异步的,具体请参见此处。如果不知道您正在使用哪些框架,很难得出结论。 - DaveAlden
@DaveAlden,谢谢您的回复。请查看我的更新问题。 - soumya
从你的HTML片段来看,你可能正在使用jQuery Mobile?如果是这样,那么是哪个版本?如果不是的话,请举一个在视图之间导航的例子。 - DaveAlden
是的,我正在使用jQuery移动版本:jQuery Mobile 1.4.5 @daveAlden。 - soumya
6个回答

7
问题在于在iOS 9.0 UIWebview(Cordova/Phonegap使用的)中设置window.location.hash是异步的 - 有关详细信息,请参见此错误报告
当使用jQuery Mobile时,这会导致问题,默认情况下,它使用window.location.hash在“页面”之间进行导航。它还会影响使用此机制的弹出窗口/对话框/选择菜单等。
您可以通过阻止jQuery Mobile自动监听/使用location.hash来解决此问题:
$(document).on("deviceready", function(){
    $.mobile.hashListeningEnabled = false;
});

但是,我发现这会对Android产生一些副作用,例如导致硬件返回按钮无法工作,因此我使用cordova-plugin-device将其专门针对iOS 9进行了定位:

$(document).on("deviceready", function(){
    if(device.platform === "iOS" && parseInt(device.version) === 9){
        $.mobile.hashListeningEnabled = false;
    }
});

请注意,我使用的是navigator.app.backHistory()而不是window.history.back()hashListeningEnabled = false一起使用——这可能会有所不同。
或者您可以使用此插件在iOS 8和9上使用新的WKWebView。Safari在iOS 8+上使用WKWebView,因此在iOS 9上在浏览器中查看JQM网站不会遇到这些问题。由于iOS 8中WKWebView中的错误,cordova-ios 3仍然使用UIWebView,但即将推出的cordova-ios 4将支持iOS 9+的WKWebView核心插件。请注意,在Cordova / Phonegap应用程序中使用WKWebView时还需要考虑其他因素,例如需要在XHR响应上要求CORS标头等更严格的安全性。

在ondeviceReady方法中使用$.mobile.hashListeningEnabled = false;后,导航点击无法正常工作。之前,无论向前导航点击次数如何,它都会弹回到加载页面。 - soumya
如果那不起作用,WKWebView可能是更好的选择。 - DaveAlden
我应该在界面构建器中用WKWebView替换UIWebView吗?我会尝试一次。 - soumya
不知道你是如何构建它(本地还是云服务),但是尝试一下,看看WKWebView是否解决了这些问题。如果你选择使用WKWebView,请确保进行全面的回归测试,因为它可能会引发其他问题。 - DaveAlden
你知道如何在mainViewController中使用WKWebView而不是UIWebview吗?(这里我有一个函数 - (void)webViewDidFinishLoad:(UIWebView*)theWebView) - soumya
让我们在聊天中继续这个讨论 - soumya

4

我认为是A标签的默认操作导致了这个错误。因此,我只需在点击处理程序函数的末尾添加return false 来阻止默认操作。

这样做可以解决问题。

  • html

<a id="back-btn">返回</a>

  • javascript

    $('#back-btn').on('click', function(e) {
           window.history.go(-1);
           return false;
        })
    

我尝试了多种变化,这个对我起作用了。只需添加一个 [return false;] 就可以完成任务。 - DanIreland

2

禁用推送状态对我起了作用:

$.mobile.pushStateEnabled = false;


@lan Drake,这个真的很好用,不像我的解决方案。它没有出现任何“当状态=1时导航开始”的问题。感谢您提供的解决方案。 - soumya
禁用了 pushState 后,我可以使用 "navigator.app.backHistory()" 返回吗? - Nimesh khatri

2

解决方案:

这一行代码解决了我的问题:

 history.go(0); 

我已将 window.history.back() 替换为 history.go(0);

现在在 iOS 9 上它已经正常工作了。

在 index.html 文件中

   <script type="text/javascript">$.mobile.hashListeningEnabled = false;</script>

在onDeviceReady函数中添加以下内容:

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 );
        }
    }
}

设备操作系统版本验证(因为history.go(0)仅适用于iOS 9),在iOS 9之前的版本中,window.history.back()可以完美工作。

现在,请将以下代码替换为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();
}

为了解决控制台中出现的“Failed to load webpage with error: CDVWebViewDelegate: Navigation started when state=1”错误信息,请在CDVWebViewDelegate.m文件中添加以下代码:

在 - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType 方法中,注释掉下面这段代码:

/*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];
}*/

导航功能正常,但是我在控制台中看到了这行信息:CDVWebViewDelegate: Navigation started when state=1,网页加载失败。 - soumya
有人知道这个行为是一个小问题还是一个重大问题吗? - soumya

1

@Sujania,

根据PhoneGap团队的说法,iOS9目前尚未得到官方支持。这个问题可能是iOS9中的另一个bug。您可能需要等待修复。

PhoneGap Build iOS 9支持状态
http://community.phonegap.com/nitobi/topics/phonegap-build-ios-9-support-status

首要问题:在Cordova-iOS 4.0.0之前,iOS 9没有得到官方支持,而Cordova团队正在努力解决这个问题。但是一些简单的配置更改可以解决一些问题。

目前,Cordova Bug存储库报告了4个错误。截至本文撰写时,您的问题似乎尚未列入该存储库。

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


无论你使用什么,正如论坛帖子所述,“iOS 9在Cordova-iOS 4.0.0之前不受官方支持”。这意味着要么创建一个解决方法,要么等待官方支持。或者向cordova提交错误报告。或者等待其他人创建解决方法。就我而言,我不从事领先的工作,所以跟进并不适合我。--祝你好运。 - user3255670

0

试试这个

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);
        }
      }

谢谢您的回复。但是问题仍然存在。我的视图没有正确地弹回。 - soumya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接