我们正在开发一个混合应用程序,我们在我们的应用程序中使用谷歌地图 API。当我们尝试在地图中加载 2000 个数据标记时,它崩溃了。地图不会在 IOS6、IOS5 中崩溃。它只发生在 IOS7 中。是否对 ios7 应用程序进行了任何与内存相关的更改。
11 回答
如前所述,iOS7 对内存使用更加严格。这种行为发生在其他浏览器(如 Chrome)中,因此当应用程序达到内存使用上限时,就会出现崩溃。
我只使用 Gmaps javascript API 和 jQuery 隔离了两个测试用例:
使用 100 个标记进行测试:一切正常
http://jsfiddle.net/edfFq/6/embedded/result
使用 3000 个标记进行测试:发生崩溃
http://jsfiddle.net/edfFq/7/embedded/result/
$(document).ready(function () {
var map;
var centerPosition = new google.maps.LatLng(40.747688, -74.004142);
var options = {
zoom: 2,
center: centerPosition,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map($('#map')[0], options);
for (var i=0;i<2800;i++){
var position = new google.maps.LatLng(40*Math.random(),-74*Math.random());
var marker = new google.maps.Marker({
position: position,
map: map
});
}
});
如果您的地图使用标签、自定义图标和集群,您可以使用更少的标记来实现崩溃。
我们有一个 web 应用程序,它在 iOS7 上也有很多标记。因此,我们仔细研究了 iPad 使用的内存。
装有 iOS7 的 iPad mini(和 iPad3):
内存使用率越来越高,浏览器崩溃在300-400MB之间。
装有 iOS6 的 iPad 3
内存使用量约为200MB,一切都很好。
iPad 1 与 iOS5
内存使用量只有100MB左右,一切都很好。
结论
所以这不仅仅是内存限制——这绝对是 iOS safari 上的一个巨大错误!直到现在(iOS 7.0.3)这还没有解决。
在使用 Google Maps 遇到类似问题后,我尝试隔离一个最小的测试用例。我想看看这是否是一个更普遍的内存管理问题。
这段仅在数组中存储随机数据的代码使 16GB iPad mini 上 IOS 7 上的 Safari 崩溃:
function randomString(length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))];
return result;
}
var arr = []
for (var i=0;i<5000;i++) {
// one character is two bytes in JavaScript, so 512 chars is 1Kb:
o = randomString(512, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
arr.push(o);
}
您可以通过访问 http://vici.org/memtest.html使用自己的浏览器尝试此测试。该页面上的脚本将尝试以 1Mb 为步长申请 50Mb 的内存。该脚本显示了一个正在运行的计数器,因此您将看到您的浏览器的执行情况以及它何时崩溃(如果确实如此)。该脚本将每个 ip / 用户代理组合的结果存储在数据库中,以便能够得出一些结论。
平均而言,IOS 6 (n=12) 允许脚本声称大约 12Mb。IOS 7 (n=47) 允许脚本要求大约 15 Mb。这些不是硬性限制。两组的标准偏差都非常高,约为 12 Mb。在 Xcode 模拟器中,Safari 甚至根本不会崩溃(声称完整的 50Mb,可能是因为它可以访问更多 RAM)。
所以我们可以得出结论,这个问题不是由 IOS 7 为 Safari 留出更少的内存引起的。正如 Philipp Kühn 所建议的,问题似乎是——在某些特定情况下?- 与 IOS 6 相比,Safari 消耗的内存要多得多。关于原因的一条线索可以在https://discussions.apple.com/message/23837361#23837361找到一个包含 200 个 div 和以下 CSS 的页面
div {
-webkit-backface-visibility: hidden;
}
崩溃野生动物园。
使用 Leaflet 库似乎可以绕过地图问题(请参阅https://code.google.com/p/gmaps-api-issues/issues/detail?id=和https://github.com/Leaflet/Leaflet/ pull/2149 ) 但是,Leaflet 不是通过更改 css 而是通过更改 javascript 级别来规避内存不足的崩溃。传单现在规避了诸如
context = this
这表明 Safari 不会清理未使用的对象。只要 Apple 不修复 Safari,也许 Google 可以做出类似于 Leaflet 家伙所做的改变?
与此同时,Apple 发布了 IOS7.1,它并没有完全解决崩溃问题,但肯定会减少它们的发生频率。
好消息!我们将我们的应用程序框架从谷歌切换到传单,它运行良好,没有崩溃,我们检查了调试,它运行非常高的内存,但从不崩溃。如果您还没有使用 Leaflet,它完全适用于 iOS 7,
我们的应用程序的行为与上述用户相同;在 iOS 7 之前一切都运行良好,但之后就崩溃了。这个问题确实似乎是一个内存问题。您可以通过检查设备上的崩溃报告日志来进行验证。
由于我们的应用程序对客户来说至关重要,我们不能坐等 Apple 的修复。在我们的案例中,修复涉及三个特定策略:
Javascript代码优化。我们的应用程序开发得非常快,并且在没有大量代码规划的情况下从原型转变为工作系统。在我们的系统中,我们能够通过优化代码实现显着的内存增益。这意味着删除未使用的变量;看看您是否碰巧将所有标记存储到初步数组中作为数据库的响应。成功加载所有内容后,删除这些旧数组和未使用的变量。此外,考虑限制包含的库,并采用常见的 Javascript/jQuery 最佳优化实践。
空的信息窗口。下一个节省内存的策略来自不使用数据预加载每个标记的信息窗口屏幕。我们剥离了每个信息窗口,除了一个具有唯一 ID 的空 div,然后通过 Ajax 单击时异步加载。当您取出所有不必要的信息窗口数据时,数千个标记所节省的成本相当大。我们加载了大约 10,000 个标记。用户体验也没有受到太大影响,因为预加载和 Ajax 加载时间的差异可以忽略不计。
- 最大的区别,也许是关于 iOS 7 内存泄漏所在的线索,来自简单地减少一次显示在屏幕上的标记数量。每个应用程序都会有所不同,但我们发现将结果降低到 500 个标记或更少会导致系统稳定而不会崩溃。我们的策略只是根据用户行为加载和清除可见标记数组。例如,如果用户的特定过滤器选择导致超过 500 个标记,我们只需限制来自数据库的结果。从视觉上看,结果集似乎仍然很大,从用户体验的角度来看,与看到数千个标记并没有太大区别。在这两种情况下,用户仍然需要过滤和缩小结果以得到可管理的结果。
这成功了!我们的应用程序现在没有崩溃。考虑到这个问题给我带来的时间量(更不用说沮丧!),希望这些策略能给你一个起点,让你的应用程序恢复正常工作。如果您想要更具体的内容,请随时与我们联系。祝你好运!
我们对谷歌地图上的标签有同样的问题。当地图放大应用程序崩溃时。这在升级到 IOS 7 后开始发生。我正在尝试不同的选项,例如在“拖动”和“空闲”等事件中删除和添加标签。此代码有效,但仍然发生崩溃。但不经常。我希望有人可以更好地解决这个问题。
google.maps.event.addListener(Map.gmap, 'drag', function () {
$('.arrowSite_box').remove(); // remove labels
});
google.maps.event.addListener(Map.gmap, 'idle', function () {
loadMarkers(results); // add labels
});
我有同样的问题并尝试了一些东西。我在设置标记时禁用了动画(我一次添加了大约 30 个),现在它似乎不再崩溃了。希望有帮助。
嘿...我也面临着类似的问题。所以,我尝试了这个:
我在视图控制器和自定义插件的“didReceiveMemoryWarning”方法中清除了应用程序缓存,并在 CDVPlugin 类的“onMemoryWarning”方法中将属性和变量设置为 NIL。这种方法对我有用。到目前为止,我没有遇到任何崩溃。希望这可以帮助。
如果您正在处理大量标记,请尝试使用MarkerClusterer。它将显着降低并发标记的数量,并且在我们的例子中它防止了崩溃。
我相信 IOS7 的内存上限为 5Mb(更长的电池寿命),它曾经是 50Mb 或类似的东西。由于该上限受操作系统限制,因此无论您使用的是 Chrome、Safari 还是其他浏览器,超过上限都会崩溃。
我从 SQL 测试了我的接收数据限制为 20,它适用于我的 iphone(pad)上的所有浏览器。
似乎已在 iOS 7.1 中修复
昨天在 iOS 7.0.6 上,我的地图使用 3,000 多个标记会使 Mobile Safari 崩溃。今天升级 iPad 后,我可以在 Mobile Safari 中加载超过 15,000 个标记的地图。