事件起因

事情是这样的:产品上线发布,突然出现了问题。运营Gg过来反应,当场给露珠演示,运营同事的手机是iphone,bug确实是存在的。奇怪的是露珠用了其他iphone手机(借别人的,露珠的是吊死安卓机),却没有发现这个问题。仔细询问,同事说他最近刚刚升级的ios9,于是问题最初定位在操作系统上。接下来检查代码,发现运行正常,逻辑也没错。问题就卡到这里了。没办法,线上问题,fiddler替换本地脚本调试,一级一级alert,从项目文件到底层库,最后定位到了backbone。查看backbone源码,发现问题结症:_updateHash方法中有改变hash值的方法,location.hash和location.replace两个,不管执行的是哪个,hash值不会立即改变!也就是说早ios9中hash在地址栏中变化有延迟!

backbone的hash跳转机制

一、代码层:在backbone(以下简称bk)中,利用的是route.navigate方法进行路由的跳转,bk框架会根据你传入的hash值,手动替换地址栏中的hash,接着调用loadUrl方法去内存中读取传入的路由配置,执行回掉函数。大概流程类似如下代码:

route.navigate(手动调用跳转)--->_updateHash(更新地址栏中的url)->loadUrl(去内存中读取注册的路由事件)->callback(执行回掉函数);

二、浏览器层:浏览器层是不受代码控制的,但是浏览器提供给了js监听url的事件,现代浏览器中都支持onhashchange事件,当然,这你也可以在start中配置默认采用popstate事件监听,如果是老旧的浏览器,bk采取的是定时器时刷新的监听方式。不管哪一种方式,都是为了检测地址栏中hash值得变化。通过浏览器的回退和前进功能,hash值会跟随变化,而浏览器本身不会刷新,所以,通过各种对url变化事件的监听,可以做到响应自定义的事件。大概流程类似如下的代码:

back/forward(浏览器前进或者后退)------>onhashchange(出发hash值变化)----->checkUrl(执行loadUrl之前检测url,该方法主要应付的事浏览器的行为,代码层则会return)---->loadUrl(通过查找内存找到对应路由的回掉)---->callback(执行自定义回掉函数);

一切都井井有条地进行着,直到ios9的发布,而你们这群有钱人又急着把自己的果机升级。结果是,如果你在回掉函数中需要处理url的话,那么你得到的是旧的url不会是最新的。

补救和兼容

为了查找结症,露珠在百度无果后google到了同样在这方面遇到的问题的同行。没想到为了这个bug,老外在github上炸开了锅,各种吐槽ios9,不管是bk或者anglar都存的开发者都遇到了这个hash改变延迟的问题。然后还有的大神给出了解决的方案(链接在文章末尾中露珠会发出来)。同时卤煮为了验证,自己在ios9真机上调试了。以下是露珠的代码调试和输出的结果,问题都出在_updateHash这个方法上面:

为了解决延迟问题,我们的方案当然也是延迟。通过测试,hash值的变化大概在ios9下游9~30ms(一次一次地alert结果,不太准确),所以,我们可以将回掉函数延迟>30ms时间执行。我们把loadUrl延迟了大概50ms,50ms对于用户来说是一个很短的过程,所以,对于那些没有出毛病的系统来说也是可以接受的。于是,我们把源码(1599行左右)改成一下面这样的:

if (options.trigger) {
var self = this;//this存入全局变量中
setTimeout(function(){//延迟50ms执行
return self.loadUrl(fragment);
}, 50);
}

通过检测,通过了各个系统的测试。目前还是比较稳定。

结语

露珠坚持不动框架源码的原则,不在万不得已的情况下坚决不动框架源码。但是一旦出现了类似系统的bug,为了修复,修改源码也是一种无奈。苹果这种大公司,一个小bug可能牵动的是全球成千上万的开发者。希望苹果公司早日修复此bug。而不是要我们这些开发者写兼容。同时也希望露珠的博客对于正在开发bk或者其他单页面应用的读者诸君有些许的帮助。

参考文档

https://github.com/driftyco/ionic/commit/e5b85dfc47dee788382c7da8f3a8abed7c2d38ac

https://github.com/angular/angular.js/issues/12241

最后感谢老大威哥对露珠的鼓励,和帮助露珠查到的文档。

IOS9.0中hash值的bug与解决方案的更多相关文章

  1. Core 1.0中publishOptions Include的bug

    "publishOptions": { "include": [ "wwwroot", "Views", "A ...

  2. JS 中offset 的小bug 与解决方案。

    一.发现bug准备工作,先定义一个div,然后给div加上样式    效果图如图所示: 二.编写正常的代码,同时给div加上一个id     会发现div图会向左缩进...直至消失. 三.添加代码bo ...

  3. 开发中遇到的一些bug及解决方案

    一.在使用UIStackView时报“UIStackView before iOS 9.0”.

  4. ios开发之 -- stringByAddingPercentEscapesUsingEncoding方法被替换 iOS9.0

    最近在项目中,发现之前的一个方法已经不被建议使用了. 该方法名即题目中提到的: stringByAddingPercentEscapesUsingEncoding,这个方法是用来进行转码的,即将汉字转 ...

  5. 从客户端(ctl00$ContentPlaceHolder1$result="<?xml version="1.0" ...")中检测到有潜在危险的 Request.Form 值。

    ylbtech-Error-WebForm:从客户端(ctl00$ContentPlaceHolder1$result="<?xml version="1.0" . ...

  6. 判断修改的中的值,用前面的,否则容易获得空值;this.dataGridView1.Rows[i].Cells[0].EditedFormattedValue; VS bool b = (bool)this.dataGridView1.Rows[i].Cells[0].Value;

    判断修改的中的值,用前面的,否则容易获得空值:this.dataGridView1.Rows[i].Cells[0].EditedFormattedValue;  VS     bool b = (b ...

  7. MemSQL Start[c]UP 2.0 - Round 1 F - Permutation 思维+线段树维护hash值

    F - Permutation 思路:对于当前的值x, 只需要知道x + k, x - k这两个值是否出现在其左右两侧,又因为每个值只有一个, 所以可以转换成,x+k, x-k在到x所在位置的时候是否 ...

  8. Java 实现C#中的String.format效果 解决("我是{0},今年了","whaozl") bug

        /**      * 需要引入com.alibaba.fastjson.1.2.8      * 两种调用方式      * String template1="我是{0},今年{1 ...

  9. 整理iOS9适配中出现的坑(图文)

    原文: http://www.cnblogs.com/dsxniubility/p/4821184.html 整理iOS9适配中出现的坑(图文)   本文主要是说一些iOS9适配中出现的坑,如果只是要 ...

随机推荐

  1. Android开发之Java集合类性能分析

    对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和 Map这三大类的集合,今天Android吧(ard8. ...

  2. 2.View绘制分析笔记之onMeasure

    今天主要学习记录一下Android View绘制三部曲的第一步,onMeasure,测量. 起源 在Activity中,所有的View都是DecorView的子View,然后DecorView又是被V ...

  3. 从vue1.0到vue2.0遇到的一些问题的记录

    1.取消v-el的使用方式,改为refs使用 获取指定的dom元素 html:<div ref="div"></div> js: $refs.div 问题: ...

  4. Git安装

    前面说了很多废话,说得再好,还不如实践一次.要想使用Git,首先得安装.这次实验主要是实践怎样安装Git. 安装与检查是否安装成功 1. 在Linux(Ubuntu)上安装 上篇的Git简介已经介绍过 ...

  5. Redis——学习之路二(初识redis服务器命令)

    上一章我们已经知道了如果启动redis服务器,现在我们来学习一下,以及如何用客户端连接服务器.接下来我们来学习一下查看操作服务器的命令. 服务器命令: 1.info——当前redis服务器信息   s ...

  6. 四则运算app代码上传GITHUB

    团队: 郭志豪:http://www.cnblogs.com/gzh13692021053/ 杨子健:http://www.cnblogs.com/yzj666/ 刘森松:http://www.cnb ...

  7. Manthan, Codefest 16(B--A Trivial Problem)

    B. A Trivial Problem time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  8. java try(){}catch(){}自动资源释放

    从 Java 7 build 105 版本开始,Java 7 的编译器和运行环境支持新的 try-with-resources 语句,称为 ARM 块(Automatic Resource Manag ...

  9. bzoj 3202: [Sdoi2013]项链

    Description 项链是人体的装饰品之一,是最早出现的首饰.项链除了具有装饰功能之外,有些项 链还具有特殊显示作用,如天主教徒的十字架链和佛教徒的念珠. 从古至今人们为了美化人体本身,也美 化环 ...

  10. linux安装oracle11g

    准备oracle安装文件 Oracle11gR2包含两个文件linux_11gR2_database_1of2.zip和linux_11gR2_database_2of2.zip,将这两个文件通过SS ...