7

I have created a simple UIViewController that creates and destroys a GMSMapView.

- (void)viewDidAppear:(BOOL)animated
{
  if ( !m_disappearing_bc_segue )
    {
       [super viewDidAppear:animated] ;

       GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude: self.location.latitude
                                                           longitude: self.location.longitude
                                                                zoom:9 ] ;

       m_mapView = [GMSMapView mapWithFrame:CGRectMake(0, 0, 320, 420) camera:camera];

       m_mapView.myLocationEnabled = NO ;

       [m_mapView setMapType: kGMSTypeTerrain] ;

       m_mapView.delegate = self ;

      [self.view addSubview:m_mapView] ;
      [self.view sendSubviewToBack:m_mapView] ;
}



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

  [m_mapView clear] ;
  [m_mapView stopRendering] ;
  [m_mapView removeFromSuperview] ;
  m_mapView = nil ;
}

I have used Instruments with the Allocations instrument. The test is easy. In a UINavigation ViewController, push the view, hit back and repeat. There is about 40kb leak each time you push and pop the view containing the GMSMapView described above. I have an screenshot from the Instruments to illustrate this, but stackoverflow does not allow me to post it. I can send to someone by email if interested.

Am I doing something wrong or missing out something?

user2101384
  • 375
  • 1
  • 3
  • 14
  • Why do you need each time to recreate `GMSMapView`? – Sergey Kuryanov Mar 19 '13 at 16:38
  • Any chance adding m_mapView.delegate = nil; before saying m_mapView=nil will solve it? It may... – Stanislav Dvoychenko Mar 21 '13 at 14:41
  • @SergeyKuryanov Basically to free memory. Each GMSMapView consumes some serious memory. I have a mini-view (half of the screen) and a button drives you to see a maximized version. When I return from the maximized version, I want to throw it away. – user2101384 Mar 28 '13 at 23:41
  • Sorry for offtopic, but I tried to migrate my own project to GMaps, but I am not satisfied with it. If it has memory leak I can only suggest you not to show another view with map, but increase size of current. – Sergey Kuryanov Mar 29 '13 at 01:44
  • @SergeyKuryanov I have filed a bug [link][https://code.google.com/p/gmaps-api-issues/issues/detail?id=5188] There is no much else to do. – user2101384 Mar 29 '13 at 14:02
  • @StanislavDvoychenko the m_mapView.delegate is weak (as it should be). I suspect the memory leak comes with from some code that do things in C++ and std::vector, and it is not freed when the objC class is deallocated. Thanks for the suggestion anyway! – user2101384 Mar 29 '13 at 14:05
  • @user21010384:As my gmsmapview caused me a leak of 10mb everytime i visit the mapscreen .Thanks for your help in ViewWillDisappear method which made me to reduce to 40kb.Did u get any solution ? – ArunMak Nov 13 '13 at 09:40

1 Answers1

2

What worked for me was removing the @try clause I had in dealloc:

@try {
    [self.mapView removeObserver:self forKeyPath:@"myLocation"];
}
@catch (NSException *exception) {
}

My intention was to remove self as observer when the ViewController is dealloc'd (ironically to avoid a memory issue), and ignore the exception if it is not an observer.

Apparently @try somehow retains the mapView, which makes it stay in memory (via ARC). See why here: Why does "try catch" in Objective-C cause memory leak?.

After removing @try clause (and conditioning the removeObserver with some flag to avoid the exception), the memory went back to behave normally!

Community
  • 1
  • 1
mllm
  • 17,068
  • 15
  • 53
  • 64