3

I've got Google Map embedded in a View Controller in a Map on an iPhone. I can create my map using:

GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:39.93
                                                        longitude:-75.17
                                                             zoom:12];
mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];

// use GPS to determine location of self
mapView_.myLocationEnabled = YES;
mapView_.settings.myLocationButton = YES;
mapView_.settings.compassButton = YES;

Now, I want to add a kml file (from a URL) that displays a route. I would imagine there is something within GMSMapView to allow this either as a layer or something else, but I'm not having any luck. I've seen the KMS Tutorial but that uses some other kit, MK something. Anyway, is there a way I can load a KML file using the Google Maps for iOS API?

Saxon Druce
  • 17,406
  • 5
  • 50
  • 71
ryang
  • 93
  • 1
  • 6

3 Answers3

4

I know this question is more than 1 year old but I couldn't find any solution, so I hope my solution will be useful.

You can load KML into GMSMapView using iOS-KML-Framework. I've ported this code from a project that was using KML-Viewer

Add method for parsing KML from the given URL, make sure you pass correct app bundle to dispatch_queue_create():

- (void)loadKMLAtURL:(NSURL *)url
{
    dispatch_queue_t loadKmlQueue = dispatch_queue_create("com.example.app.kmlqueue", NULL);

    dispatch_async(loadKmlQueue, ^{
        KMLRoot *newKml = [KMLParser parseKMLAtURL:url];

        [self performSelectorOnMainThread:@selector(kmlLoaded:) withObject:newKml waitUntilDone:YES];
    });
}

Handle the KML parsing result or error:

- (void)kmlLoaded:(id)sender {
    self.navigationController.view.userInteractionEnabled = NO;

    __kml = sender;

    // remove KML format error observer
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kKMLInvalidKMLFormatNotification object:nil];

    if (__kml) {
        __geometries = __kml.geometries;

        dispatch_async(dispatch_get_main_queue(), ^{
            self.navigationController.view.userInteractionEnabled = YES;

            [self reloadMapView];
        });
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.navigationController.view.userInteractionEnabled = YES;

            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
                                                                message:NSLocalizedString(@"Failed to read the KML file", nil)
                                                               delegate:nil
                                                      cancelButtonTitle:NSLocalizedString(@"OK", nil)
                                                      otherButtonTitles:nil];
            [alertView show];
        });
    }
}

Go over the geometry items from KML and add them to the GMSMapView as markers:

- (void)reloadMapView
{
    NSMutableArray *annotations = [NSMutableArray array];

    for (KMLAbstractGeometry *geometry in __geometries) {
        MKShape *mkShape = [geometry mapkitShape];
        if (mkShape) {
            if ([mkShape isKindOfClass:[MKPointAnnotation class]]) {
                MKPointAnnotation *annotation = (MKPointAnnotation*)mkShape;

                GMSMarker *marker = [[GMSMarker alloc] init];
                marker.position = annotation.coordinate;
                marker.appearAnimation = kGMSMarkerAnimationPop;
                marker.icon = [UIImage imageNamed:@"marker"];
                marker.title = annotation.title;
                marker.userData = [NSString stringWithFormat:@"%@", geometry.placemark.descriptionValue];
                marker.map = self.mapView;

                [annotations addObject:annotation];
            }
        }
    }

    // set bounds in next run loop.
    dispatch_async(dispatch_get_main_queue(), ^{

        GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] init];

        for (id <MKAnnotation> annotation in annotations)
        {
            bounds = [bounds includingCoordinate:annotation.coordinate];
        }

        GMSCameraUpdate *update = [GMSCameraUpdate fitBounds:bounds];
        [self.mapView moveCamera:update];
        [self.mapView animateToViewingAngle:50];
    });

}

At the end of the last method we're updating the camera view to fit all the markers that were added to the map. You can remove this part if it's not needed.

Community
  • 1
  • 1
f0xik
  • 101
  • 5
  • You seem to be doing a lot more passing off to the main thread than is strictly required... – Wain Feb 13 '15 at 20:43
  • @Wain, you may be right. The original code is not mine, so I haven't had a chance to review its efficiency. Just ported it to Google Maps SDK yesterday. – f0xik Feb 13 '15 at 21:29
0

KML is not yet supported in the SDK. Please file a feature request in the issue tracker.

skarE
  • 5,880
  • 2
  • 23
  • 23
0

This is how I solved similar problem using mentioned iOS-KML-Framework.

#import <GoogleMaps/GoogleMaps.h>
#import "KML.h"

@property (weak, nonatomic) IBOutlet GMSMapView *mapView;

- (void)loadZonesFromURL:(NSURL *)url {

KMLRoot* kml = [KMLParser parseKMLAtURL: url];

for (KMLPlacemark *placemark in kml.placemarks) {
    GMSMutablePath *rect = [GMSMutablePath path];

    if ([placemark.geometry isKindOfClass:[KMLPolygon class]]) {
        KMLLinearRing *ring = [(KMLPolygon *)placemark.geometry outerBoundaryIs];

        for (KMLCoordinate *coordinate in ring.coordinates) {
            [rect addCoordinate:CLLocationCoordinate2DMake(coordinate.latitude, coordinate.longitude)];
        }

        GMSPolygon *polygon = [GMSPolygon polygonWithPath:rect];
        polygon.fillColor = [UIColor colorWithRed:67.0/255.0 green:172.0/255.0 blue:52.0/255.0 alpha:0.3];
        polygon.map = self.mapView;

    }

}


}
Alex Sh.
  • 579
  • 5
  • 17