Google Maps SDK for iOS using Swift 4

Google Maps SDK for iOS using Swift 4

Many iOS apps use Google Maps. This is a very common feature, so I have decided to prepare an ultimate guide on Google Maps SDK for iOS. This tutorial covers everything that you might possibly need. My goal is to create a story where readers will request features, so I can expand it. Everything will be documented in this post!

Installation

Before we start coding, we must install the Google Maps iOS SDK first (duh!). You might prefer some other dependency manager, but I would stick with CocoaPods which I highly recommend being used.

Create a Podfile inside your project root directory, and copy the following code:

source 'https://github.com/CocoaPods/Specs.git'
target 'YOUR_TARGET_NAME' do
  pod 'GoogleMaps'
end

All you need to do is changing the YOUR_TARGET_NAME string with a real value. Save the file and close it. Open the Terminal and cd to the root directory of the project and type pod install. You’re done!

RECOMMENDED FOR YOU: Speed up Swift compile time

Obtain an API Key 

In order to use the Google Maps iOS SDK, you will need an API Key. To generate the key you will need to visit the Google API Console.
Create a project, and navigate to Credentials. Then, click Generate Credentials and pick API Key. You will need to provide your projects bundle id. The key is generated by the unique bundle id, so if it’s changed the Google Maps services won’t work!

Go to your project, and in your AppDelegate.swift class add import GoogleMaps and then copy the following code to application(_:didFinishLaunchingWithOptions:):

GMSServices.provideAPIKey("YOUR_API_KEY")



#1 Add a Map 

I will start by showing you how to set up the map together with a basic marker. The code that you will see here (as well as in any other tutorial) is tested in parallel as I write. Let’s start!


Visit your UIViewController (where you need to add the map) and create a custom UIView with the size you need. Assign the GMSMapView class as a Custom Class on that newly created UIView (see the screenshot below). Also, don’t forget to connect the delegate.

 

Finally, some code!

Let’s get back to the UIViewController and write some code. ⌨️
️In the below snippet, I have added the whole class so you can get a better picture of what is going on. By using GMSCameraPosition we are telling the map which coordinates to take as a center point. To show a simple marker on the map, just use the showMarker() function. At the end of the file add an extension which will “store” all of the GMSMapViewDelegate methods that we will need.

import UIKit
import GoogleMaps

class ViewController: UIViewController {

    @IBOutlet fileprivate weak var mapView: GMSMapView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let camera = GMSCameraPosition.camera(withLatitude: 37.36, longitude: -122.0, zoom: 6.0)
        mapView.camera = camera
        showMarker(position: camera.target)
    }
    
    func showMarker(position: CLLocationCoordinate2D){
        let marker = GMSMarker()
        marker.position = position
        marker.title = "Palo Alto"
        marker.snippet = "San Francisco"
        marker.map = mapView
    }
}
extension ViewController: GMSMapViewDelegate{
    
}

 

#2 Delegate methods

I will now introduce you to some GMSMapViewDelegate methods and their powers. ✊

GMSMarker InfoWindow

InfoWindow can be seen upon tapping GMSMapViewDelegate on the marker. The good thing about this is that it’s fully customizable. You can attach your own UIView with whatever components you need. Assuming that in most cases people will use a custom InfoWindow, I have written an example how to achieve this.

extension ViewController: GMSMapViewDelegate{
    /* handles Info Window tap */
    func mapView(_ mapView: GMSMapView, didTapInfoWindowOf marker: GMSMarker) {
        print("didTapInfoWindowOf")
    }
    
    /* handles Info Window long press */
    func mapView(_ mapView: GMSMapView, didLongPressInfoWindowOf marker: GMSMarker) {
        print("didLongPressInfoWindowOf")
    }

    /* set a custom Info Window */
    func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
        let view = UIView(frame: CGRect.init(x: 0, y: 0, width: 200, height: 70))
        view.backgroundColor = UIColor.white
        view.layer.cornerRadius = 6
        
        let lbl1 = UILabel(frame: CGRect.init(x: 8, y: 8, width: view.frame.size.width - 16, height: 15))
        lbl1.text = "Hi there!"
        view.addSubview(lbl1)
        
        let lbl2 = UILabel(frame: CGRect.init(x: lbl1.frame.origin.x, y: lbl1.frame.origin.y + lbl1.frame.size.height + 3, width: view.frame.size.width - 16, height: 15))
        lbl2.text = "I am a custom info window."
        lbl2.font = UIFont.systemFont(ofSize: 14, weight: .light)
        view.addSubview(lbl2)

        return view
    }
}
  • didTapInfoWindowOf() detects when the user taps on the InfoWindow.
  • markerInfoWindow() adds the custom UIView that we want to show to the marker.
  • didLongPressInfoWindowOf() detects when the InfoWindow has been long pressed.

 

 

Drag GMSMarker 

Another interesting feature in GMSMapViewDelegate is the dragging of the marker. What is more important, it can be achieved with the minimum amount of code possible. All you have to do is turn on the “switch”, by calling marker.isDragabble=true on the above-created marker (section #1).

extension ViewController: GMSMapViewDelegate{
    
    //MARK - GMSMarker Dragging
    func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) {
        print("didBeginDragging")
    }
    func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) {
        print("didDrag")
    }
    func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) {
        print("didEndDragging")
    }
}

In order to drag the marker, you will need to use a long press. If you need to get notified when the user started and ended his dragging, you will need to implement these 3 delegate methods.

  • didBeginDragging notifies only once when the dragging has started.
  • didDrag notifies while the marker is being dragged.
  • didEndDragging notifies only once when the dragging has ended.

GMSMarker Position

Ever needed to change the GMSMarker position while tapping on the map? Well, GMSMapViewDelegate offers a solution for that as well. With a single delegate method, you can intercept the coordinates (latitude and longitude) of the tapped area and assign its value to the marker.

extension ViewController: GMSMapViewDelegate{
    func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D){
        marker.position = coordinate
    }
}
  • didTapAt() returns the coordinate from the tapped area on the map



#3 Shapes

The Google Maps iOS SDK has some simple ways for drawing a shape. I will cover how to draw with polylines, polygons, and circles.

Polylines

Shapes come from lines. And to draw lines you need to use Polylines. The object that will help us with the drawing is called GMSPolyline. To create a polyline, you will need to create a path using GMSMutablePath. It will create the path only if it’s containing two or more points.

func drawRectange(){
    /* create the path */
    let path = GMSMutablePath()
    path.add(CLLocationCoordinate2D(latitude: 37.36, longitude: -122.0))
    path.add(CLLocationCoordinate2D(latitude: 37.45, longitude: -122.0))
    path.add(CLLocationCoordinate2D(latitude: 37.45, longitude: -122.2))
    path.add(CLLocationCoordinate2D(latitude: 37.36, longitude: -122.2))
    path.add(CLLocationCoordinate2D(latitude: 37.36, longitude: -122.0))
    
    /* show what you have drawn */
    let rectangle = GMSPolyline(path: path)
    rectangle.map = mapView
}

 

 

If you have used the above example, you will get a rectangular shape like this one above.

Some other useful tips:

  • To remove a polyline from the map just call mapView.clear().
  • You can change the color of the line by using polyline.strokeColor=.black.
  • Change the width of the line by calling polyline.strokeWidth=3.

Polygon

Polygon is almost the same as Polylines. It works on the same approach, just contains a few more tweaks.For example, GMSPolygonwill draw a shape and then you can add a fillColor to fill the area that was drawn. Here is an example how a polygon looks like.

func polygon(){
    // Create a rectangular path
    let rect = GMSMutablePath()
    rect.add(CLLocationCoordinate2D(latitude: 37.36, longitude: -122.0))
    rect.add(CLLocationCoordinate2D(latitude: 37.45, longitude: -122.0))
    rect.add(CLLocationCoordinate2D(latitude: 37.45, longitude: -122.2))
    rect.add(CLLocationCoordinate2D(latitude: 37.36, longitude: -122.2))
    
    // Create the polygon, and assign it to the map.
    let polygon = GMSPolygon(path: rect)
    polygon.fillColor = UIColor(red: 0.25, green: 0, blue: 0, alpha: 0.2);
    polygon.strokeColor = .black
    polygon.strokeWidth = 2
    polygon.map = mapView
}

 

 

I hope that this tutorial was fun so far. There are more interesting things waiting for you below.

Radius (Circle)

We are reaching the final shape, which is drawing a circle. This is probably the easiest shapes of all since it’s always the same (duh!).
To achieve this, we need to use theGMSCircle class. Here, we are not passing a path, but only one coordinate which will represent the circle center, and a radius (in meters).

func circle(){
    let circleCenter = CLLocationCoordinate2D(latitude: 37.35, longitude: -122.0)
    let circ = GMSCircle(position: circleCenter, radius: 1000)
    circ.map = mapView
}

 

 

TheGMSCircle class contains the same properties as the polygon like fillColor,strokeColorand strokeWidth .

#4 Properties and Settings

This part will cover a few properties and settings that are used very often when having Google Maps in your app. Let’s take a look at them…

Change Marker Icon

If you ever needed to change the marker icon, here is how. The GMSMarker contains two different properties (yes, two) for changing the marker icon.

  • marker.icon=UIImage(named: "image.png")this is the first approach where you just pass the image and the default one gets replaced.
  • marker.iconView=customViewthe Google Maps SDK gives you a chance to add a custom view instead of just an image. This is mostly used for more complex markers, like if you want to add some animation, or multiple components (not just a single image). Note that the icon property gets overwritten when iconView is called.

Add My Location Button

The My Location Button appears in the bottom right corner. By clicking the button it will animate the map to the user’s current location. To do this just set mapView.settings.myLocationButton = true and the button will appear.

 

Zoom Controls

For those who are seeking this kind of feature. Google Maps SDK for iOS doesn’t support this. You will need to write your own logic. In the Android SDK, the map comes with the zoom controls, but I am afraid that is not the case in iOS. Anyways, all you need to do is add two buttons with + and – icons and callmapView.animate(toZoom: zoom)

Control Gestures

You can turn on/off any gesture that you can see on the map. For example, you might need to disable the zooming or turn off scrolling. There are a total of four gestures available for control.

mapView.settings.scrollGestures = false
mapView.settings.zoomGestures   = false
mapView.settings.tiltGestures   = false
mapView.settings.rotateGestures = false

I hope that you have enjoyed this tutorial. If you want to read more on Google Maps SDK for iOS just write me a comment, and I would be very happy to expand this tutorial with your request. Also, if you have found something useful please or share this story to spread the knowledge. Cheers!

RECOMMENDED FOR YOU: Introducing Clean Swift Architecture (VIP)

Leave a Reply

Your email address will not be published. Required fields are marked *