geminiCoder
geminiCoder

Reputation: 2906

Google Maps SDK causing leak iOS 7

Getting leaks in profiler when google map loads. I have created a very simple View Controller based on google's example code and Im finding I am getting a leak when the map loads. I believe the leak is in the SDK itself. Has anyone come across this problem and found a solution?

enter image description here

enter image description here

basic View Controller

//
//  JRCViewController.m
//  GoogleMapsInterface
//
//  Created by Jake Cunningham on 15/01/2014.
//  Copyright (c) 2014 Jake Cunningham. All rights reserved.
//

#import "JRCViewController.h"

@interface JRCViewController (){
BOOL firstLocationUpdate_;
GMSMapView *mapView;
}


@end


@implementation JRCViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.
    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.868
                                                            longitude:151.2086
                                                                 zoom:6];
    mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];

    [mapView addObserver:self
               forKeyPath:@"myLocation"
                  options:NSKeyValueObservingOptionNew
                  context:NULL];

    self.view = mapView;

    dispatch_async(dispatch_get_main_queue(), ^{
        mapView.myLocationEnabled = YES;
    });

}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {

    if (!firstLocationUpdate_) {
        // If the first location update has not yet been recieved, then jump to that
        // location.
        firstLocationUpdate_ = YES;
        CLLocation *location = [change objectForKey:NSKeyValueChangeNewKey];
        mapView.camera = [GMSCameraPosition cameraWithTarget:location.coordinate
                                                        zoom:14];
    }
}



@end

Upvotes: 4

Views: 1633

Answers (1)

Lena Bru
Lena Bru

Reputation: 13947

I found the reason for the problem. Like you, I thought that their "demo code" was supposed to work as is. Not understanding that this line

GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.868
                                                            longitude:151.2086
                                                                 zoom:6];

The very first line in the demo was actually the problem. If you are not in Australia (which is where this location point is) You result in loading the entire world map (tiles) into the memory of the app, which is wrong!

If you know approximately which continent/country/state your map will be used or better yet! get the user's location BEFORE you show the map, and load the map at that location.

So your initialization of the map should be this:

CLLocation *location = [self getUserLocation]; //probably from shared prefs, even if its 100 miles away from where the user actually is, is better than loading another continent.

and then your viewDidLoad would look like this

- (void)viewDidLoad
{
    [super viewDidLoad];
     CLLocation *location = [self getUserLocation]; //<== very important!
    // Do any additional setup after loading the view, typically from a nib.
    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:location.coordinate.latitude
                                                            longitude:location.coordinate.longitude
                                                                 zoom:15];
    mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];

    [mapView addObserver:self
               forKeyPath:@"myLocation"
                  options:NSKeyValueObservingOptionNew
                  context:NULL];

    self.view = mapView;

    dispatch_async(dispatch_get_main_queue(), ^{
        mapView.myLocationEnabled = YES;
    });

}

The zoom level also has an effect on this -> the bigger the zoom is, the less tiles you load into the memory.

also I added code in viewWillDisappear (assuming that viewDidLoad will run again when the given ViewController will be needed again)

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
        [self.mapView clear];
        [self.mapView removeFromSuperview] ;
        self.mapView.delegate = nil;
        self.mapView = nil ;
}

This helped my app from having to use 140 MB of ram to just 56! When app normal is between 40 and 45.

Upvotes: 5

Related Questions