When developing an iOS application for automotive project http://megasos.com we faced the need for Google Maps integration in iOS. It turned to be not quite as trivial for starting from iOS 6.0 version Apple removed Google Maps from the default set of applications. Standard MapKit has also been completely redesigned and adapted to work with a new Apple mapping service.
I will not go into all the pros and cons of this change, but the most noticeable disadvantage, typical for any new map service, is not sufficiently complete portrayal of all objects (or even a complete lack of these objects).
There are at least three options for iOS 6 Google Maps integration:
- Using standard MapKit with a portrayal of Google maps in overlay mode;
- Using GoogleMapsSDK;
- Developing of your own MapKit using GoogleMaps API.
The first option is good in that it does not require much effort — uploading of overlay is implemented by just several lines of code and there is no need to redo the process of withdrawal of objects on the map. But it also has drawbacks, the main of which is the reduction of productivity and significant increase in traffic consumption (because both cards are loaded).
The second option turned to be much more optimal from the point of view of consumed traffic and performance. But there is a completely different process of withdrawal of «annotations» here (in Google Maps, they are called «markers»). Therefore, the adaptation of the application will need much more time. Also, quite a serious drawback was the lack of ready-made solutions for the clustering of markers and the need to implement this functionality from scratch.
The third option seemed to me the most time consuming, and we abandoned it right away.
First you need to create a key for the application in Google API's Console. Then download the framework from the Google developer site and add it to the project (and with it a dozen of more dependent frameworks).
After that, create an example of GMSMapView class, display it in the main View, and admire Google maps in our application!
This process is thoroughly described in the documentation of GoogleMapsSDK for iOS. While there aren't too many markers on the map, it all works quite quickly :).
At first glance, the process of adding and controlling markers in GoogleSDK looks pretty simple.
You need to create a class in MapKit for the MKAnnotation protocol and add annotations to the map. Then create in the
mapView:viewForAnnotation: method the View already for the marker itself and change its appearance.
In GoogleMapsSDK it is done in just several lines:
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(-33.86, 151.20); GMSMarker * marker = [GMSMarker markerWithPosition:position]; marker.title = @"Sydney"; marker.snippet = @"Australia"; marker.icon = [UIImage @"marker.png"] marker.map = self.mapView;
But if markers keep accumulating, than substantial freezes appear. I think this can be explained by the fact that GoogleMapsSDK immediately adds all markers images on the map, unlike MapKit, which creates only a list of annotations on the map, and the appearance of markers is generated no more than in the process of navigation and only for those annotations, which fall within the scope of the
To solve this problem, you can hide the markers that do not fall within the scope of the
But it does not help in those cases when the user maximizes the scale (as all the markers will still remain in scope). And here, as in the case with a standard MapKit, we need clustering (grouping and combining the markers).
For GoogleMapsSDK you will have to create a class of markers clustering treatment from scratch (unlike for MapKit, for which you can find a lot of different implemented solutions on GitHub).
For more information on clustering on maps, I will write a bit later.
Custom InfoWindow (Callouts)
Contents outlook for Info Window can be arranged by the method:
(UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(id
But there is another problem that I encountered in the transition from MapKit to GoogleMapsSDK — this is lack of interactivity of these windows.
GMSMapView adds not the presentation generated by this function, but its original image. I.e., you can not change its appearance or to handle an event associated with a particular element that is on it.
The following solution was found: I added a presentation of the information window for the active marker over the presentation of GMSMapView. The only downside here is the need to constantly change its position when calling
didChangeCameraPosition, so it doesn't stay away from the marker.