事件起因

事情是这样的:产品上线发布,突然出现了问题。运营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. 将一个实体数据保存到不同的数据表中<EntityFramework6.0>

    2014-11-22声明方式 public class Product { [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] public ...

  2. swift 手机号码正则表达式 记录一下

    func isTelNumber(num:NSString)->Bool { var mobile = "^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$&qu ...

  3. windows 共享文件夹 给 mac

      假设我要共享文件夹A (1)在windows上, 共享该文件夹 (2)然后macbook 和 pc  连接同一个网络 (3)在finder选择连接服务器 (4)输入服务器地址smb://**** ...

  4. java-并发-线程对象

    浏览以下内容前,请点击并阅读 声明 每个线程都和类Thread的实例相关,有两种基本的使用Thread对象来创建并发应用的方法: 直接控制线程的创建和管理,每次需要开始一个异步任务使简单地实例化Thr ...

  5. DB Scan算法的分析与实现

    摘自:http://www.cnblogs.com/weixliu/archive/2012/12/08/2808815.html 根据上面第二个数据集的簇的形状比较怪异,分簇结果应该是连起来的属于一 ...

  6. 有关DOM

    一般地,节点至少拥有nodeType.nodeName和nodeValue这三个基本属性. 节点类型不同,这三个属性的值也不相同 nodeType nodeType属性返回节点类型的常数值.不同的类型 ...

  7. js排序算法总结——冒泡,快速,选择,插入,希尔,归并

    相信排序是任何一个程序猿都会用到的东西,今天简单总结记录下常见的排序算法. 一.冒泡排序 说起冒泡排序,可能每个人都不会陌生,实现思路相当简单明了,就是不停的对数组进行两两比较,将较大(较小)的一项放 ...

  8. 2016 正确 sublime安装PHPcs PHPcodesniffer代码规范提示插件,修正网上部分不详细描述

    对你有助请点赞,请顶,不好请踩------送人玫瑰,手留余香!-------------------14:37 2016/3/212016 正确 sublime安装PHPcs PHPcodesniff ...

  9. View的弹性滑动

    View的弹性滑动 实现弹性滑动的思想:将一次大的滑动分成若干次小的滑动并在一个时间段内完成,具体的实现方式有很多,如通过Scroller.Handler#postDelayed以及Thread#sl ...

  10. ASP.NET导出Excel文件

    第一种最常见,并且最简单的方式,直接把GridView导出,导出格式为文本表格形式. protected void btnSaveExcel_Click(object sender, EventArg ...