Getting started with MapKit for iOS
This tutorial explains how install and setup MapKit library and create a map with a placemark for a specific location.
Step 1. Get the MapKit API key
Before you can use MapKit SDK in your application, you need the API key.
-
Go to the Developer Dashboard.
-
Log in to your Yandex account or create a new one.
-
Click Connect APIs and choose MapKit Mobile SDK.
-
Enter information about yourself and your project, select a pricing plan, and click Continue.
-
After your API key is successfully created, it will be available in the API Interfaces → MapKit Mobile SDK tab.
Note
It takes about 15 minutes to activate API keys.
Step 2. Add the MapKit library to your project
Use CocoaPods to add the library to the project.
-
Go to the directory with the Xcode project.
-
Create the Podfile to list dependencies from other libraries:
pod init
-
Open the Podfile in a text editor and add a dependency for your target:
use_frameworks! # The lite library only contains the map, traffic layer, # LocationManager, and UserLocationLayer # and lets you download offline maps (in the paid version only). pod 'YandexMapsMobile', '4.8.1-lite' # The full library supplements lite version features with car routing, # bike routing, pedestrian routing, and public transport routing, # search, suggest, geocoding, and panorama display. # pod 'YandexMapsMobile', '4.8.1-full'
-
Run the following command in the project directory:
pod install
To open the project file, run the following command:
open *.xcworkspace
Step 3. Provide the API key to MapKit
The MapKit SDK requires you to set up the API key in the YMKMapKit(Factory).setApiKey method.
Set your API key in the application(_:didFinishLaunchingWithOptions:)
method of the application delegate and instantiate the YMKMapKit
object:
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
YMKMapKit.setApiKey("Your API key")
YMKMapKit.sharedInstance()
}
Note
If you're using a multi-module application and want to initialize MapKit in a method different from application(_:didFinishLaunchingWithOptions:)
, call the onStart()
method after creating the MapKit object:
YMKMapKit.setApiKey("MAPKIT_API_KEY")
YMKMapKit.sharedInstance().onStart()
Step 4. Add the map
Initialize the map in the needed view controller:
override func viewDidLoad() {
super.viewDidLoad()
mapView.mapWindow.map!.move(
with: YMKCameraPosition(
target: YMKPoint(latitude: 55.751225, longitude: 37.62954),
zoom: 15,
azimuth: 0,
tilt: 0
),
animation: YMKAnimation(type: YMKAnimationType.smooth, duration: 5),
cameraCallback: nil
)
}
Build and run your application. There's an example of the Activity with the tappable map:
Maps support multiple actions by default: move, rotate, change the zoom, and tilt.
Without additional setup, the map will be shown with the smallest possible zoom for the user's screen.
To change a map's position or zoom, use the YMKMap.move(with:animation:cameraCallback:) method:
private func move(_ map: YMKMap) {
let cameraPosition = YMKCameraPosition(
target: YMKPoint(latitude: 55.751225, longitude: 37.62954,
zoom: 17.0,
azimuth: 150.0,
tilt: 30.0
)
map.move(with: cameraPosition, animation: YMKAnimation(type: .smooth, duration: 1.0))
}
The YMKMap.move(with:animation:cameraCallback:) call accepts the YMKCameraPosition argument, which fully defines the map's position, zoom, tilt, and azimuth.
There's an example of the Activity after applying the move to the map:
Step 5. Note the following
MapKit stores weak references to the Listener objects passed to it. You need to store references to them in memory yourself:
Note
All Listener objects must be inherited from the NSObject
class.
internal class CameraListener: NSObject, YMKMapCameraListener {
func onCameraPositionChanged(
with map: YMKMap?,
cameraPosition: YMKCameraPosition,
cameraUpdateReason: YMKCameraUpdateReason,
finished: Bool
) {
// Do something
}
}
let cameraListener = CameraListener()
override func viewDidLoad() {
super.viewDidLoad()
mapView.mapWindow.map!.addCameraListener(with: cameraListener)
}
Note
By default, the methods of any Listener objects and platform interfaces are called on the main thread unless the method documentation specifies otherwise.
-
The minimum supported version for the M1 emulator is iOS 13.
-
The M1 emulator doesn't support OpenGL, so make sure to pass
vulkanPreferred: true
to theYMKMapView
andYMKPanoView
constructors. This setting is only required for the emulator build. -
Recommended linking flag:
-ObjC
.
Step 6. Display a placemark on the map
Let's modify the application such that you can show a tappable placemark on the map.
-
Add a
png
resource for the placemark image to the project.For example, we have the image named
placemark_icon.png
in ourAssets
directory. -
Add the placemark for the YMKMap.mapObjects collection to the specific location.
Obtain the image for our placemark using
UIImage(named:)
constructor. Add the placemark for the YMKMap.mapObjects collection to the specific location using YMKMapObjectCollection.addPlacemark(with:image:) method:private func addPlacemark(_ map: YMKMap) { let image = UIImage(named: "placemark_icon") ?? UIImage() let placemark = map.mapObjects.addPlacemark() placemark.geometry = YMKPoint(latitude: 55.751225, longitude: 37.62954 placemark.setIconWith(image) }
You can also add text to the placemark and customize it's style using YMKPlacemarkMapObject.setTextWithText(_:style:) method:
placemark.setTextWithText( "Sample placemark", style: YMKTextStyle( size: 10.0, color: .black, outlineColor: .white, placement: .top, offset: 0.0, offsetFromIcon: true, textOptional: false ) )
-
To subscribe to created placemark's taps use YMKMapObject.addTapListener(with:) method.
Firstly, we need to create a listener class, that implements the YMKMapObjectTapListener.onMapObjectTap(with:point:) method:
final private class MapObjectTapListener: NSObject, YMKMapObjectTapListener { init(controller: UIViewController) { self.controller = controller } func onMapObjectTap(with mapObject: YMKMapObject, point: YMKPoint) -> Bool { AlertPresenter.present( with: "Tapped point", message: "\((point.latitude, point.longitude))", from: controller ) return true } private let controller: UIViewController }
Then we can create a listener object and assign it to the placemark:
private lazy var mapObjectTapListener: YMKMapObjectTapListener = MapObjectTapListener(controller: self) private func addPlacemark(_ map: YMKMap) { placemark.addTapListener(with: mapObjectTapListener) }
Build and run your application. There's a placemark with your custom image on the map. Tap the placemark, and the message toast will show up:
Source code
For full code samples from the tutorial, see the MapWithPlacemark
application in our GitHub repository.