web-dev-qa-db-ja.com

iOS 7 MKMapViewによるメモリリークの防止

アプリでメモリリークが発生することに気づきましたが、MKMapViewを取り出すと、メモリの問題は解消されます。

理論をテストするために、MKMapViewが含まれているビューをプッシュし、ポップしてプッシュするビューを持つ、シンプルなプロジェクトを作成しました。これ以上何もない。ビューコントローラーにコードはなく、すべてストーリーボードを介して行われます。

マップビューに行ったり来たりすると、マップが含まれているビューをプッシュしてポップした後、約3MB開始します。これは、メモリの約15倍の230MBです。

誰かこれを見た?かなり大きなバグのようです。 MKMapViewを使用して別の方法でリークを防ぐことはできますか?

enter image description here

31
codercat

私は同じ問題に直面し、(Stackoverflowのおかげで)MKMapTypeviewWillDisappearを変更し、デリゲートを割り当て解除/ nilに設定することで修正しました。デリゲートにメッセージを送信するためです。これはMKMapViewDelegateプロトコルリファレンスに記載されています。

デリゲートを設定したMKMapViewオブジェクトを解放する前に、そのオブジェクトのデリゲートプロパティをnilに設定してください。これを実行できる1つの場所は、マップビューを破棄する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;
}

お役に立てれば

14
iAhmed

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
}
4
fede1608

私が見つけた最良の解決策は、MKMapViewのインスタンスをデリゲートに置くことです。インスタンスは1回だけ割り当てます。

その後、MapViewが必要なときはいつでも、デリゲートのMapViewを使用するだけです。

私の場合、ビューがdisDisappearになるとすぐにアノテーションを削除する必要がありました(マップに古いアノテーションを付けないため)。

  - (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];
    }
}
4
xGoPox