GMSMapView:如何管理内存?

Posted

技术标签:

【中文标题】GMSMapView:如何管理内存?【英文标题】:GMSMapView: how to manage memory? 【发布时间】:2013-05-28 13:03:11 【问题描述】:

我的应用在子视图中使用了一个GMSMapView,内存使用情况如下:

地图访问前 1.25 MB; 首次访问地图后需要 21.5 MB; 放大和平移后需要 30 MB(有时会超过 30)

据我对 Instruments 的了解,没有泄漏。问题是,我收到内存警告,并且经常会关闭应用程序。显然,GoogleMaps 正在使用该应用程序的大部分内存。如何在 didReceiveMemoryWarning() 中释放其中的一些内容?

是否可以在应用中使用 Google 地图并管理其内存使用,至少足以防止其导致内存关闭?

这是 GoogleMaps-ios-1.3.0。

更新:

我的记忆数字很差(使用分配工具而不是活动监视器)。以下是正确的值:

地图访问前 8.8 MB 第一次访问地图后需要 57 MB 65 MB,峰值接近 80 MB。缩放和平移后

这显然属于 256 MB RAM 设备(例如 iPod Touch 4G)的“故障”范围,并解释了内存警告和偶尔出现的问题。

有人在 256 MB 设备上的应用中成功运行 Google 地图吗?

【问题讨论】:

尝试在地图不在屏幕上时调用 stopRendering。这将释放内存资源。 但是当用户滚动和缩放并且警告开始出现(有时,关闭)时该怎么办?即,没有机会停止渲染。基本上,应用程序是否只需要让 GMSMap 将其驱动到内存破产? :-) @user2444264 你找到任何解决方案了吗,我面临同样的问题 没有。 iOS 版 Google 地图存在一些突出的错误(例如,请参阅 code.google.com/p/gmaps-api-issues/issues/detail?id=5202),所以我不情愿地切换回 MapKit。 @user2444264 mapkit也有同样的问题 【参考方案1】:

尝试在您的视图控制器中使用此代码:

- (void)viewWillDisappear:(BOOL)animated
    [super viewWillDisappear:animated] ;
    [m_mapView clear];
    [m_mapView stopRendering] ;
    [m_mapView removeFromSuperview] ;
    m_mapView = nil ;

我试过了,它确实释放了一些 GMSMapView 内存。

【讨论】:

我使用 Swift,所以我不熟悉 Obj-C,但我建议在 deinit 函数中调用它而不是 viewWillDisappear。 @Rogoon 我对 Swift 不太熟悉,但我知道 viewWillDisappear() 的使用方式与在 Obj-C 中的使用方式完全相同,因此我认为没有必要将其放在其他地方。 @turingtested 听起来很公平。老实说,我不记得我为什么这么建议了。我记得有一些奇怪的问题,当我不想要它时调用 viewWillDisappear。可能是在当前地图顶部推送视图时。当我返回地图视图时,地图被删除并且没有重新设置。也许我当时只是没有使用 viewWillAppear 来正确地重新初始化地图。 只有在 viewWillDisappear 之后调用时才会减小一点大小。一旦地图视图再次加载,内存大小就会增加一倍。!如果我保持内存不变,我该怎么办。 它减少了 40% 的 CPU 使用率。停止创建大量 Google 地图矢量切片线程。 :)【参考方案2】:

地图 API 使用大小为 256 x 256 像素的图块。这些以 32 位/像素纹理的形式加载到内存中,因此它们将使用 256 x 256 x 4 = 256kb/tile。

如果您有一台 1024 x 768 的 iPad,那么您需要 4 x 3 = 12 个图块 = 3MB。但是,这仅在您的视图恰好与图块边界完全对齐的情况下 - 实际上它会跨越边界,因此您可能需要 5 x 4 = 20 个图块 = 5MB。

但是,如果您缩小到几乎要显示下一个较低缩放级别的点,则每个图块将被绘制为其全尺寸的一半以上,因此您需要 10 x 8 = 80 个图块 = 20MB .

然后,如果您有 Retina 设备,它实际上会加载下一个更高缩放级别的图块,因此每个维度需要两倍的图块(以匹配屏幕的像素而不是点),因此您需要 20 x 16 = 320 个图块 = 80MB。

iPhone 5 的类似计算结果为 240 个图块 = 60MB。

因此,如果您计算地图仅用于图块所需的内存量,不计算用于内部处理的任何开销或其他内存,它的计算量会很大。所以你可能无能为力。当存在内存压力时,地图 SDK 已经释放了未使用的图块 - 但它无法释放渲染当前视图所需的图块。

这意味着您唯一的选择可能是减少您自己代码中的内存使用量。

对于我的应用程序,我不得不改变它在 iPad 1 上的工作方式,因为它内存不足并且经常崩溃。对于其他设备,我发现它工作正常。

可能的解决方法的一些想法可能是减小地图视图的大小,或将缩放级别调整为整数值。这对用户来说都不是很好,但它们可能有助于避免崩溃。

【讨论】:

感谢您的详细回答。你说,“当存在内存压力时,地图 SDK 已经释放了未使用的图块”。我没有看到内存使用量因内存警告而下降。我一直在(256 MB 内存)iPod Touch 4G 上对此进行测试,并认为你是对的,除非我减小屏幕尺寸,否则它不会成功。 很难确定,但在我的应用程序中,我通过释放尽可能多的内存来处理内存警告,但如果 SDK 没有尽可能释放磁贴,那么我的应用程序将是经常崩溃 :) 所以我认为它会尽可能地释放瓷砖,但它可以走多远是有限制的,这仍然可以解决很多问题。【参考方案3】:

就我而言,我在两个视图控制器中背靠背有两个 mapView,所以我弹出视图控制器并从超级视图中删除地图视图。

override func onBtnBack() 
        self.navigationController?.popViewController(animated: true)
        self.mapView.removeFromSuperview()

【讨论】:

【参考方案4】:

我也被 GMSMapview 使用的巨大内存卡住了。这是 google map sdk 中的严重问题,我认为 Google 团队正在努力解决这个问题。 他们还修复了 1.9.0 版本中的一些内存回收问题 其他减少内存的方法-

    尽量减小 GMSMapView 的大小

    使用最新版本 1.9.0 - 2014 年 10 月。

使用以下链接下载最新的sdk-

https://developers.google.com/maps/documentation/ios/releases

【讨论】:

以上是关于GMSMapView:如何管理内存?的主要内容,如果未能解决你的问题,请参考以下文章

如何在iphone中获取gmsmapview的坐标中心

MapView 相机在 iOS Swift 中没有改变

如何从内存中卸载 GMSMapView?

-[GMSMapView animateToCameraPosition:]:无法识别的选择器发送到实例

如何获取谷歌地图标记的 UIView 实例?

谷歌地图代表