TC McCarthy
TC McCarthy

Reputation: 31

Adding geojson layer to google map in iOS

I am writing my first iOS native app. I am trying to load a GeoJSON layer onto a google map in the app (map comes from the google maps sdk) but I can't find any way to do it. I'm proficient in the google maps javascript API but I'm sensing things in Swift are very different.

How can I load a GeoJSON layer onto a map in a native iOS app?

Upvotes: 3

Views: 3762

Answers (3)

Anjali jariwala
Anjali jariwala

Reputation: 445

All you have to do is add your geoJSon file in your project, Then add below code:

func addMapView() {
    let zoomLevel = locationManager.accuracyAuthorization == .fullAccuracy ? preciseLocationZoomLevel : approximateLocationZoomLevel
    let options = GMSMapViewOptions()
    options.camera = GMSCameraPosition.camera(withLatitude: defaultLocation.coordinate.latitude, longitude: defaultLocation.coordinate.longitude, zoom: zoomLevel)
    options.frame = self.vwMap.bounds
    
    mapView = GMSMapView(options: options)
    mapView.settings.myLocationButton = true
    mapView.isMyLocationEnabled = true
    vwMap.addSubview(mapView)
}

 func renderGeoJSON() {
    guard let path = Bundle.main.path(forResource: "Wadi Khat", ofType: "geojson") else {
        return
    }
    let url = URL(fileURLWithPath: path)
    geoJsonParser = GMUGeoJSONParser(url: url)
    geoJsonParser.parse()
    renderer = GMUGeometryRenderer(map: mapView, geometries: geoJsonParser.features)
    renderer.render()
}

Call both of these methods in ViewDidLoad, Attaching sample geoJSon file: Wadi Khat.geojson

Upvotes: 0

FredFlinstone
FredFlinstone

Reputation: 956

First add your geoJSON file to your project. And if you have google maps set up than you can use the following:

let path = Bundle.main.path(forResource: "GeoJSON_sample", ofType: "json")
let url = URL(fileURLWithPath: path!)
geoJsonParser = GMUGeoJSONParser(url: url)
geoJsonParser.parse()

let renderer = GMUGeometryRenderer(map: mapView, geometries: geoJsonParser.features)
renderer.render()

Upvotes: 3

hoogw
hoogw

Reputation: 5535

As of today, I have not see any api can parse geojson into google map shapes on ios. Therefor you have to parse it on your own, parse it into array, then loop through array get each feature, get each geometry, properties, and create shape based on feature type(point, line, polygon)

Here is sample from mapbox to draw a line, you have to extend it to point and polygon.

// Perform GeoJSON parsing on a background thread
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(backgroundQueue, ^(void)
{
    // Get the path for example.geojson in the app's bundle
    NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"example" ofType:@"geojson"];

    // Load and serialize the GeoJSON into a dictionary filled with properly-typed objects
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[[NSData alloc] initWithContentsOfFile:jsonPath] options:0 error:nil];

    // Load the `features` dictionary for iteration
    for (NSDictionary *feature in jsonDict[@"features"])
    {
        // Our GeoJSON only has one feature: a line string
        if ([feature[@"geometry"][@"type"] isEqualToString:@"LineString"])
        {
            // Get the raw array of coordinates for our line
            NSArray *rawCoordinates = feature[@"geometry"][@"coordinates"];
            NSUInteger coordinatesCount = rawCoordinates.count;

            // Create a coordinates array, sized to fit all of the coordinates in the line.
            // This array will hold the properly formatted coordinates for our MGLPolyline.
            CLLocationCoordinate2D coordinates[coordinatesCount];

            // Iterate over `rawCoordinates` once for each coordinate on the line
            for (NSUInteger index = 0; index < coordinatesCount; index++)
            {
                // Get the individual coordinate for this index
                NSArray *point = [rawCoordinates objectAtIndex:index];

                // GeoJSON is "longitude, latitude" order, but we need the opposite
                CLLocationDegrees lat = [[point objectAtIndex:1] doubleValue];
                CLLocationDegrees lng = [[point objectAtIndex:0] doubleValue];
                CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(lat, lng);

                // Add this formatted coordinate to the final coordinates array at the same index
                coordinates[index] = coordinate;
            }

            // Create our polyline with the formatted coordinates array
            MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:coordinatesCount];

            // Optionally set the title of the polyline, which can be used for:
            //  - Callout view
            //  - Object identification
            // In this case, set it to the name included in the GeoJSON
            polyline.title = feature[@"properties"][@"name"]; // "Crema to Council Crest"

            // Add the polyline to the map, back on the main thread
            // Use weak reference to self to prevent retain cycle
            __weak typeof(self) weakSelf = self;
            dispatch_async(dispatch_get_main_queue(), ^(void)
            {
                [weakSelf.mapView addAnnotation:polyline];
            });
        }
    }

});

here is swift code for line, you have to expend it to point and polygon

 // Parsing GeoJSON can be CPU intensive, do it on a background thread
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        // Get the path for example.geojson in the app's bundle
        let jsonPath = NSBundle.mainBundle().pathForResource("example", ofType: "geojson")
        let jsonData = NSData(contentsOfFile: jsonPath!)

        do {
            // Load and serialize the GeoJSON into a dictionary filled with properly-typed objects
            if let jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: []) as? NSDictionary {

                // Load the `features` array for iteration
                if let features = jsonDict["features"] as? NSArray {
                    for feature in features {
                        if let feature = feature as? NSDictionary {
                            if let geometry = feature["geometry"] as? NSDictionary {
                                if geometry["type"] as? String == "LineString" {
                                    // Create an array to hold the formatted coordinates for our line
                                    var coordinates: [CLLocationCoordinate2D] = []

                                    if let locations = geometry["coordinates"] as? NSArray {
                                        // Iterate over line coordinates, stored in GeoJSON as many lng, lat arrays
                                        for location in locations {
                                            // Make a CLLocationCoordinate2D with the lat, lng
                                            let coordinate = CLLocationCoordinate2DMake(location[1].doubleValue, location[0].doubleValue)

                                            // Add coordinate to coordinates array
                                            coordinates.append(coordinate)
                                        }
                                    }

                                    let line = MGLPolyline(coordinates: &coordinates, count: UInt(coordinates.count))

                                    // Optionally set the title of the polyline, which can be used for:
                                    //  - Callout view
                                    //  - Object identification
                                    line.title = "Crema to Council Crest"

                                    // Add the annotation on the main thread
                                    dispatch_async(dispatch_get_main_queue(), {
                                        // Unowned reference to self to prevent retain cycle
                                        [unowned self] in
                                        self.mapView.addAnnotation(line)
                                    })
                                }
                            }
                        }
                    }
                }
            }
        }
        catch
        {
            print("GeoJSON parsing failed")
        }
    })

Upvotes: 1

Related Questions