【问题标题】:Stop iOS 7 MKMapView from leaking memory阻止 iOS 7 MKMapView 泄漏内存
【发布时间】:2013-12-06 22:52:25
【问题描述】:

我注意到我的应用程序泄漏了内存,但如果我将MKMapView 取出,内存问题就会消失。

为了测试这个理论,我做了一个非常简单的项目,它有一个视图,它可以推送一个带有MKMapView 的视图,然后弹出并推送。而已。视图控制器中没有代码,一切都通过故事板完成。

如果我来回切换到地图视图,它会在推送和弹出包含地图的视图后开始大约 3MB,这大约是内存的 15 倍,大约是 230MB。

其他人看到了吗?似乎是一个相当大的错误。有没有其他方法可以使用MKMapView 来防止它泄漏这么多?

【问题讨论】:

  • 我在我的应用程序中也看到了这种行为,对我来说问题很清楚:这里发生了什么?这是一个真正的内存泄漏吗(看起来是这样)并且有人弄清楚出了什么问题以及如何解决。
  • 尝试移除viewDidDisappear方法中的MKMapView,例如:[self.outMapView removeFromSuperview]; self.outMapView = nil;
  • 可能应该记录一张雷达票。
  • 搜索,您会在此处和其他论坛上找到数十个此类问题 - 提交雷达。由于地图已损坏,您无能为力
  • 在 iOS 9.x 中仍然存在问题。我通过在静态变量中存储对 MKMapView 的引用并一遍又一遍地重用同一个 Map 来解决它。

标签: ios objective-c memory-management memory-leaks mkmapview


【解决方案1】:

Swift 版本:

override func viewWillDisappear(_ animated:Bool) {
    super.viewWillDisappear(animated)
    self.applyMapViewMemoryFix()
}

func applyMapViewMemoryFix() {
    switch (self.mapView.mapType) {
    case MKMapType.hybrid:
        self.mapView.mapType = MKMapType.standard
    case MKMapType.standard:
        self.mapView.mapType = MKMapType.hybrid
    default:
        break
    }
    self.mapView.showsUserLocation = false
    self.mapView.delegate = nil
    self.mapView.removeFromSuperview()
    self.mapView = nil
}

【讨论】:

  • 即使我实现了您的解决方案,iOS 8.3/8.4 中仍然存在内存问题
  • 为我提供帮助。我在 tableView 单元格中有 mapView。从单元 deinit {} 调用此函数。现在没有内存泄漏。但我真的很有趣有一个真实的原因。
【解决方案2】:

我发现的最佳解决方案是在您的委托中拥有一个 MKMapView 实例,您只需分配一次。

然后,只要您需要 MapView,您只需使用委托的那个即可。

在我的情况下,我需要在视图消失后立即清除其中的注释(以便地图上没有旧注释)。

  - (void)viewDidLoad {
      AppDelegate *delegate = [UIApplication sharedApplication].delegate;
          if (!delegate.appModel.mapView)
             delegate.appModel.mapView = [[MKMapView alloc] initWithFrame:self.view.frame];
      self.mapView = delegate.appModel.mapView;
      [self.mapView setFrame:self.view.frame];
      [self.mapView setDelegate:self];
      [self.view addSubview:self.mapView];
   }

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.mapView removeAnnotations:self.mapView.annotations];
    for (id<MKOverlay> overlay in self.mapView.overlays) {
        [self.mapView removeOverlay:overlay];
    }
}

【讨论】:

  • 可以使用静态变量(而不是将其存储在应用程序委托变量中)
【解决方案3】:

我遇到了同样的问题,并且(感谢 Stackoverflow)通过在 viewWillDisappear 中更改 MKMapType 并将其委托解除分配/设置为 nil 来修复它。因为它仍然向委托发送消息。 这在 MKMapViewDelegate 协议参考中有记录:

在释放您设置了一个 MKMapView 对象之前 委托,记得将该对象的委托属性设置为 nil。一 你可以这样做的地方是你处理的 dealloc 方法 地图视图

.

-(void)viewWillDisappear:(BOOL)animated{
  [super viewWillDisappear:animated];
  [self applyMapViewMemoryFix];

}

- (void)applyMapViewMemoryFix{

switch (self.mkMapView.mapType) {
    case MKMapTypeHybrid:
    {
        self.mkMapView.mapType = MKMapTypeStandard;
    }

        break;
    case MKMapTypeStandard:
    {
        self.mkMapView.mapType = MKMapTypeHybrid;
    }

        break;
    default:
        break;
}
self.mkMapView.showsUserLocation = NO;
self.mkMapView.delegate = nil;
[self.mkMapView removeFromSuperview];
self.mkMapView = nil;
}

希望对你有帮助

【讨论】:

  • 没有帮助。还在漏水。
  • 是的,对我来说它还在泄漏。我在UICollcetionViewCell 中有地图视图,所以我无法从viewWillDisappear 调用此代码。在单元格的deinit 中调用它不起作用。
  • 我们有任何更新吗?它的 2018 年仍然在泄漏。 @durazno
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
  • 2019-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多