Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load a KML file URL into Google Maps using iOS API?

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?

like image 216
ryang Avatar asked Dec 06 '25 15:12

ryang


1 Answers

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.

like image 56
f0xik Avatar answered Dec 08 '25 09:12

f0xik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!