/YandexMapKit

Яндекс.Карты в SwiftUI

Primary LanguageSwift

YandexMapKit для SwiftUI

Яндекс.Карты в SwiftUI

Описание

Этот проект демонстрирует, как интегрировать библиотеку YandexMapKit в приложение на SwiftUI. YandexMapKit позволяет добавлять карты Яндекса в ваше приложение и использовать различные возможности картографических сервисов Яндекса, такие как отображение карт, маршрутизация, геокодирование и другие.

В этом репозитории содержится проект YandexMapKit (далее в качестве примера будут испоьзованы скрины из этого проета), для демонстрации используется функция преобразования координат.

Требования

  • iOS 12.0 и выше
  • Xcode 12.0 и выше
  • Swift 5.3 и выше

Установка

Проверьте установлен на вашем Mac: Homebrew, Xcode Command Line Tools и Ruby

Если нет, выполните следующие команды в терминале

Убедитесь, что у вас установлены необходимых инструментов для сборки. Если нет, установите их с помощью следующей команды:

  • Установите Xcode Command Line Tools:
$> xcode-select --install
  • Установите Homebrew, если он еще не установлен:
$> /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  • Установите необходимые пакеты с помощью Homebrew:
$> brew install autoconf automake libtool pkg-config
  • Установите Ruby через Homebrew::
$> brew install ruby

Подготовка

1) Установка CocoaPods

$> sudo gem install cocoapods
Проверка
$> pod --version
your_version
Если у вас возникнут какие-либо проблемы во время установки
  1. Ознакомьтесь с этим руководством: Документация

  2. Мне также помогли следующие действия:

    $> sudo gem uninstall cocoapods
    $> brew reinstall ruby
    $> sudo gem update --system 3.5.10
    $> sudo gem install drb -v 2.0.6
    $> sudo gem install cocoapods
    

2) Получим API ключ для работы

Подробно: Документация

Чтобы получить API ключ: нужно завести аккаунт разработчика Яндекса. Для начала зайдем в кабинет разработчика Яндекса

Авторизуйтесь в свой аккаунт. Нажмите Подключить API и выберите MapKit – мобильный SDK

Заполните информацию о своем проекте. Ваш API-ключ будет успешно создан, вскоре он понадобится.


3) Создаем проект

Создаем проект SwiftUI в XCode: yourProjectSwiftUI

Например: создадим проект YandexMapKit

Далее установим PodFile, для этого в терминале директории проекта:

$> cd yourProjectSwiftUI
$> pod init
$> open Podfile

В открывшемся PodFile добавим зависимость:

use_frameworks!
pod 'YandexMapsMobile', '4.6.1-full'

Для нашего проекта будет выглядеть следующим образом

Выполните в директории проекта команду:

$> pod install

Откройте файл проекта:

$> open *.xcworkspace

Подключение библиотеки

Добавим класс AppDelegate в проект, для этого:

  • Создадим файл AppDelegate.swift

  • Добавим следующий код в файл и устанавливаем API ключ:

     import SwiftUI
     import YandexMapsMobile
     
     class AppDelegate: NSObject, UIApplicationDelegate {
         func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
             YMKMapKit.setApiKey("Ваш API ключ")
             YMKMapKit.sharedInstance()
             return true
         }
     }
  • Добавим в проект yourProjectSwiftUI следующую строку:

     import SwiftUI
     
     @main
     struct yourProjectSwiftUIApp: App {
         
         @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
         
         var body: some Scene {
             WindowGroup {
                 ContentView()
             }
         }
     }
  • Добавим в таргет проекта:

    Privacy - Location When In Use Usage Description

Надпись (графа String) может быть любой, например: Доступ к вашей локации

В процессе сборки проекта у меня возникала проблема: "Sandbox: rsync.samba (13105)"

Решение: Изменить параметр сборки проекта Xcode

User Script Sandboxing - 'No'

Подключение карты в проект

Добавим класс LocationManager и структуру YandexMap

  • Класс LocationManager предназначен для взаимодействия с картой, выполняет роль ViewModel и отвечает за логику управления процессами

     import Foundation
     import CoreLocation
     import YandexMapsMobile
     import Combine
     
     class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {
         
         @Published var lastUserLocation: CLLocation? = nil
         private let manager = CLLocationManager()
         let mapView = YMKMapView(frame: CGRect.zero)!
         
         lazy var map : YMKMap = {
             return mapView.mapWindow.map
         }()
         
         override init() {
             super.init()
             self.manager.delegate = self
         }
         
         func pointLocation(point: YMKPoint) {
             let cameraPosition = YMKCameraPosition(target: point, zoom: 17.0, azimuth: 150.0, tilt: 30.0)
                 map.move(with: cameraPosition, animation: YMKAnimation(type: .smooth, duration: 1.0))
         }
     }
     
  • Структура YandexMap предназначена для отображения карты, тк библиотека работает с UIKit, поэтому также требуется выполнение протокола UIViewRepresentable

     struct YandexMapView: UIViewRepresentable {
         @EnvironmentObject var locationManager : LocationManager
         
         func makeUIView(context: Context) -> YMKMapView {
             return locationManager.mapView
         }
              
         func updateUIView(_ mapView: YMKMapView, context: Context) {}
     }
  • Структура MapView представляет графический интерфейс и является UI элементом (View)

     struct MapView: View {
         @EnvironmentObject var locationManager : LocationManager
         @Binding var latitude: String
         @Binding var longitude: String
         
         var body: some View {
             ZStack {
                 YandexMapView()
                     .edgesIgnoringSafeArea(.all)
                     .environmentObject(locationManager)
             }.onAppear{
                 locationManager.pointLocation(point: YMKPoint(latitude: Double(latitude) ?? 55.751263550483145,
                                                               longitude: Double(longitude) ?? 37.62967790286453))
             }
         }
     }

Добавим дизайн в проект

Создадим ListView для удобства использования MapView и добавим в ContentView:

import SwiftUI
import YandexMapsMobile
import Combine

struct ContentView: View {
    
    @State var latitude = String()
    @State var longitude = String()
    @ObservedObject var locationManager = LocationManager()
    
    var body: some View {
        ZStack{
            MapView(latitude: $latitude, longitude: $longitude)
                .environmentObject(locationManager)
            ListView(latitude: $latitude, longitude: $longitude)
                .environmentObject(locationManager)
        }
    }
}

struct ListView: View {
    @EnvironmentObject var locationManager : LocationManager
    @Binding var latitude: String
    @Binding var longitude: String
    
    var body: some View {
        VStack {
            Spacer()
            HStack {
                VStack(spacing: 10) {
                    TextField("latitude", text: $latitude)
                        .padding(10)
                        .background(.white)
                        .clipShape(Capsule())
                    TextField("longitude", text: $longitude)
                        .padding(10)
                        .background(.white)
                        .clipShape(Capsule())
                }
                Button("Start") {
                    locationManager.pointLocation(point: YMKPoint(latitude: Double(latitude) ?? 55.751263550483145,
                                                                  longitude: Double(longitude) ?? 37.62967790286453))
                }
                .padding(25)
                .background(.blue.opacity(0.7).gradient)
                .clipShape(Circle())
                .foregroundStyle(.white)
                .font(.system(size: 20, weight: .bold))
                
            }
            .padding(20)
            .background(Color(cgColor: CGColor(red: 0.3, green: 1, blue: 0.3, alpha: 1)))
        }
    }
}