mapkit-ios-demo icon indicating copy to clipboard operation
mapkit-ios-demo copied to clipboard

Поддержка SwiftUI?

Open windrunner21 opened this issue 3 years ago • 8 comments

Документация для SwiftUI была бы полезна.

windrunner21 avatar Sep 01 '21 13:09 windrunner21

Для тех кто ищет как показать карту используя SwiftUI

import SwiftUI
import YandexMapsMobile

struct YandexMapsView: UIViewRepresentable {
    
    func makeUIView(context: Context) -> YMKMapView {
        let mapView = YMKMapView(frame: CGRect.zero)
                
        return mapView
    }
         
    func updateUIView(_ uiView: YMKMapView, context: Context) {
             
    }
}

и потом в вашем нужном View

import SwiftUI

struct HomeView: View {
    
    var body: some View {
        YandexMapsView().edgesIgnoringSafeArea(.all)
    }
}

struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
    }
}

windrunner21 avatar Sep 01 '21 14:09 windrunner21

Для тех кто ищет как показать карту используя SwiftUI

import SwiftUI
import YandexMapsMobile

struct YandexMapsView: UIViewRepresentable {
    
    func makeUIView(context: Context) -> YMKMapView {
        let mapView = YMKMapView(frame: CGRect.zero)
                
        return mapView
    }
         
    func updateUIView(_ uiView: YMKMapView, context: Context) {
             
    }
}

и потом в вашем нужном View

import SwiftUI

struct HomeView: View {
    
    var body: some View {
        YandexMapsView().edgesIgnoringSafeArea(.all)
    }
}

struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
    }
}

Не пытался реализовывать функционал отображения местоположения пользователя в SwiftUI?

Dominnik avatar Sep 28 '21 13:09 Dominnik

Для тех кто ищет как показать карту используя SwiftUI

import SwiftUI
import YandexMapsMobile

struct YandexMapsView: UIViewRepresentable {
    
    func makeUIView(context: Context) -> YMKMapView {
        let mapView = YMKMapView(frame: CGRect.zero)
                
        return mapView
    }
         
    func updateUIView(_ uiView: YMKMapView, context: Context) {
             
    }
}

и потом в вашем нужном View

import SwiftUI

struct HomeView: View {
    
    var body: some View {
        YandexMapsView().edgesIgnoringSafeArea(.all)
    }
}

struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
    }
}

Не пытался реализовывать функционал отображения местоположения пользователя в SwiftUI?

Да, пытался. Коротко скажу так: использовать местоположение надо через сами функции Swift-a. Потом кидать это в Yandex View.

Подробнее:

Создаем класс, чтобы получать местоположение на изменения в геолокации. (Используем методы встроннные Swift-a)

class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {

    // Publish the user's location so subscribers can react to updates
    @Published var lastKnownLocation: CLLocation? = nil
    private let manager = CLLocationManager()

    override init() {
        super.init()
        self.manager.delegate = self
        self.manager.startUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
            self.manager.startUpdatingLocation()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // Notify listeners that the user has a new location
        self.lastKnownLocation = locations.last
    }
}

Потом создаем Observable который будет реагировать на изменения Location Manager-a. И добавляем его в updateUIView, где уже используем API от Yandex:

struct YandexMapsView: UIViewRepresentable {
    
    // Listen to changes on the locationManager
    @ObservedObject var locationManager = LocationManager()
    
    func makeUIView(context: Context) -> YMKMapView {
        let mapView = YMKMapView(frame: CGRect.zero)
        mapView.mapWindow.map.move(
            with: YMKCameraPosition(target: YMKPoint(latitude: 40.40_92_64, longitude: 49.86_70_92), zoom: 10, azimuth: 0, tilt: 0)
        )
        let userLocationViewController = UserLocationViewController()
        
        let mapKit = YMKMapKit.sharedInstance()
        let userLocationLayer = mapKit.createUserLocationLayer(with: mapView.mapWindow)
        userLocationLayer.setVisibleWithOn(true)
        userLocationLayer.isHeadingEnabled = true
        userLocationLayer.setObjectListenerWith(userLocationViewController)
        
        return mapView
    }
         
    func updateUIView(_ mapView: YMKMapView, context: Context) {
        // When the locationManager publishes updates, respond to them
        if let myLocation = locationManager.lastKnownLocation {
            centerMapLocation(target: YMKPoint(latitude: myLocation.coordinate.latitude, longitude: myLocation.coordinate.longitude), map: mapView )
            print("User's location: \(myLocation)")
        }
    }
    
    // custom functions
    func centerMapLocation(target location: YMKPoint?, map: YMKMapView) {
        guard let location = location else { print("Failed to get user location"); return }
        
        map.mapWindow.map.move(
            with: YMKCameraPosition(target: location, zoom: 18, azimuth: 0, tilt: 0),
            animationType: YMKAnimation(type: YMKAnimationType.smooth, duration: 5)
        )
    }
}

P.S. Чтобы использовать userLocationLayer.setObjectListenerWith(userLocationViewController) создай класс под протокол YMKUserLocationObjectListener

Надеюсь смог помочь.

windrunner21 avatar Sep 28 '21 13:09 windrunner21

Для тех кто ищет как показать карту используя SwiftUI

import SwiftUI
import YandexMapsMobile

struct YandexMapsView: UIViewRepresentable {
    
    func makeUIView(context: Context) -> YMKMapView {
        let mapView = YMKMapView(frame: CGRect.zero)
                
        return mapView
    }
         
    func updateUIView(_ uiView: YMKMapView, context: Context) {
             
    }
}

и потом в вашем нужном View

import SwiftUI

struct HomeView: View {
    
    var body: some View {
        YandexMapsView().edgesIgnoringSafeArea(.all)
    }
}

struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
    }
}

Не пытался реализовывать функционал отображения местоположения пользователя в SwiftUI?

Да, пытался. Коротко скажу так: использовать местоположение надо через сами функции Swift-a. Потом кидать это в Yandex View.

Подробнее:

Создаем класс, чтобы получать местоположение на изменения в геолокации. (Используем методы встроннные Swift-a)

class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {

    // Publish the user's location so subscribers can react to updates
    @Published var lastKnownLocation: CLLocation? = nil
    private let manager = CLLocationManager()

    override init() {
        super.init()
        self.manager.delegate = self
        self.manager.startUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
            self.manager.startUpdatingLocation()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // Notify listeners that the user has a new location
        self.lastKnownLocation = locations.last
    }
}

Потом создаем Observable который будет реагировать на изменения Location Manager-a. И добавляем его в updateUIView, где уже используем API от Yandex:

struct YandexMapsView: UIViewRepresentable {
    
    // Listen to changes on the locationManager
    @ObservedObject var locationManager = LocationManager()
    
    func makeUIView(context: Context) -> YMKMapView {
        let mapView = YMKMapView(frame: CGRect.zero)
        mapView.mapWindow.map.move(
            with: YMKCameraPosition(target: YMKPoint(latitude: 40.40_92_64, longitude: 49.86_70_92), zoom: 10, azimuth: 0, tilt: 0)
        )
        let userLocationViewController = UserLocationViewController()
        
        let mapKit = YMKMapKit.sharedInstance()
        let userLocationLayer = mapKit.createUserLocationLayer(with: mapView.mapWindow)
        userLocationLayer.setVisibleWithOn(true)
        userLocationLayer.isHeadingEnabled = true
        userLocationLayer.setObjectListenerWith(userLocationViewController)
        
        return mapView
    }
         
    func updateUIView(_ mapView: YMKMapView, context: Context) {
        // When the locationManager publishes updates, respond to them
        if let myLocation = locationManager.lastKnownLocation {
            centerMapLocation(target: YMKPoint(latitude: myLocation.coordinate.latitude, longitude: myLocation.coordinate.longitude), map: mapView )
            print("User's location: \(myLocation)")
        }
    }
    
    // custom functions
    func centerMapLocation(target location: YMKPoint?, map: YMKMapView) {
        guard let location = location else { print("Failed to get user location"); return }
        
        map.mapWindow.map.move(
            with: YMKCameraPosition(target: location, zoom: 18, azimuth: 0, tilt: 0),
            animationType: YMKAnimation(type: YMKAnimationType.smooth, duration: 5)
        )
    }
}

P.S. Чтобы использовать userLocationLayer.setObjectListenerWith(userLocationViewController) создай класс под протокол YMKUserLocationObjectListener

Надеюсь смог помочь.

Конечно помог :) Спасибо. Единственное, в классе UserLocationViewController не отрабатывают методы протокола (onObjectAdded, onObjectRemoved), что не даёт выставить кастомную иконку для местоположения пользователя.

Dominnik avatar Oct 01 '21 08:10 Dominnik

Для тех кто ищет как показать карту используя SwiftUI

import SwiftUI

import YandexMapsMobile

struct YandexMapsView: UIViewRepresentable {

func makeUIView(context: Context) -> YMKMapView {
    let mapView = YMKMapView(frame: CGRect.zero)
    return mapView
}
func updateUIView(_ uiView: YMKMapView, context: Context) {
}

}

и потом в вашем нужном View

import SwiftUI

struct HomeView: View {

var body: some View {
    YandexMapsView().edgesIgnoringSafeArea(.all)
}

}

struct HomeView_Previews: PreviewProvider {

static var previews: some View {
    HomeView()
}

}

Не пытался реализовывать функционал отображения местоположения пользователя в SwiftUI?

Да, пытался. Коротко скажу так: использовать местоположение надо через сами функции Swift-a. Потом кидать это в Yandex View.

Подробнее:

Создаем класс, чтобы получать местоположение на изменения в геолокации. (Используем методы встроннные Swift-a)

class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {

// Publish the user's location so subscribers can react to updates
@Published var lastKnownLocation: CLLocation? = nil
private let manager = CLLocationManager()
override init() {
    super.init()
    self.manager.delegate = self
    self.manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    if status == .authorizedWhenInUse {
        self.manager.startUpdatingLocation()
    }
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    // Notify listeners that the user has a new location
    self.lastKnownLocation = locations.last
}

}

Потом создаем Observable который будет реагировать на изменения Location Manager-a. И добавляем его в updateUIView, где уже используем API от Yandex:

struct YandexMapsView: UIViewRepresentable {

// Listen to changes on the locationManager
@ObservedObject var locationManager = LocationManager()
func makeUIView(context: Context) -> YMKMapView {
    let mapView = YMKMapView(frame: CGRect.zero)
    mapView.mapWindow.map.move(
        with: YMKCameraPosition(target: YMKPoint(latitude: 40.40_92_64, longitude: 49.86_70_92), zoom: 10, azimuth: 0, tilt: 0)
    )
    let userLocationViewController = UserLocationViewController()
    let mapKit = YMKMapKit.sharedInstance()
    let userLocationLayer = mapKit.createUserLocationLayer(with: mapView.mapWindow)
    userLocationLayer.setVisibleWithOn(true)
    userLocationLayer.isHeadingEnabled = true
    userLocationLayer.setObjectListenerWith(userLocationViewController)
    return mapView
}
func updateUIView(_ mapView: YMKMapView, context: Context) {
    // When the locationManager publishes updates, respond to them
    if let myLocation = locationManager.lastKnownLocation {
        centerMapLocation(target: YMKPoint(latitude: myLocation.coordinate.latitude, longitude: myLocation.coordinate.longitude), map: mapView )
        print("User's location: \(myLocation)")
    }
}
// custom functions
func centerMapLocation(target location: YMKPoint?, map: YMKMapView) {
    guard let location = location else { print("Failed to get user location"); return }
    map.mapWindow.map.move(
        with: YMKCameraPosition(target: location, zoom: 18, azimuth: 0, tilt: 0),
        animationType: YMKAnimation(type: YMKAnimationType.smooth, duration: 5)
    )
}

}

P.S. Чтобы использовать userLocationLayer.setObjectListenerWith(userLocationViewController) создай класс под протокол YMKUserLocationObjectListener

Надеюсь смог помочь.

Конечно помог :) Спасибо. Единственное, в классе UserLocationViewController не отрабатывают методы протокола (onObjectAdded, onObjectRemoved), что не даёт выставить кастомную иконку для местоположения пользователя.

Рад что смог помочь. Насчёт иконок пользователя, я скоро перейду на имплементацию этой части. Как найду что и как делать дам знать!

windrunner21 avatar Oct 01 '21 09:10 windrunner21

Для имплементации иконок и тд через UserLocationView Controller в классе YandexMapView просто надо поменять let userLocationViewController = UserLocationViewController() на @ObservedObject var userLocationViewController = UserLocationViewController()

@Dominnik

windrunner21 avatar Oct 04 '21 06:10 windrunner21

Спасибо большое. Как раз начала тоже заниматься этим. @windrunner21

Dominnik avatar Oct 05 '21 06:10 Dominnik

Для тех кто ищет как показать карту используя SwiftUI

import SwiftUI
import YandexMapsMobile

struct YandexMapsView: UIViewRepresentable {
    
    func makeUIView(context: Context) -> YMKMapView {
        let mapView = YMKMapView(frame: CGRect.zero)
                
        return mapView
    }
         
    func updateUIView(_ uiView: YMKMapView, context: Context) {
             
    }
}

и потом в вашем нужном View

import SwiftUI

struct HomeView: View {
    
    var body: some View {
        YandexMapsView().edgesIgnoringSafeArea(.all)
    }
}

struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
    }
}

Не пытался реализовывать функционал отображения местоположения пользователя в SwiftUI?

Да, пытался. Коротко скажу так: использовать местоположение надо через сами функции Swift-a. Потом кидать это в Yandex View.

Подробнее:

Создаем класс, чтобы получать местоположение на изменения в геолокации. (Используем методы встроннные Swift-a)

class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {

    // Publish the user's location so subscribers can react to updates
    @Published var lastKnownLocation: CLLocation? = nil
    private let manager = CLLocationManager()

    override init() {
        super.init()
        self.manager.delegate = self
        self.manager.startUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
            self.manager.startUpdatingLocation()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // Notify listeners that the user has a new location
        self.lastKnownLocation = locations.last
    }
}

Потом создаем Observable который будет реагировать на изменения Location Manager-a. И добавляем его в updateUIView, где уже используем API от Yandex:

struct YandexMapsView: UIViewRepresentable {
    
    // Listen to changes on the locationManager
    @ObservedObject var locationManager = LocationManager()
    
    func makeUIView(context: Context) -> YMKMapView {
        let mapView = YMKMapView(frame: CGRect.zero)
        mapView.mapWindow.map.move(
            with: YMKCameraPosition(target: YMKPoint(latitude: 40.40_92_64, longitude: 49.86_70_92), zoom: 10, azimuth: 0, tilt: 0)
        )
        let userLocationViewController = UserLocationViewController()
        
        let mapKit = YMKMapKit.sharedInstance()
        let userLocationLayer = mapKit.createUserLocationLayer(with: mapView.mapWindow)
        userLocationLayer.setVisibleWithOn(true)
        userLocationLayer.isHeadingEnabled = true
        userLocationLayer.setObjectListenerWith(userLocationViewController)
        
        return mapView
    }
         
    func updateUIView(_ mapView: YMKMapView, context: Context) {
        // When the locationManager publishes updates, respond to them
        if let myLocation = locationManager.lastKnownLocation {
            centerMapLocation(target: YMKPoint(latitude: myLocation.coordinate.latitude, longitude: myLocation.coordinate.longitude), map: mapView )
            print("User's location: \(myLocation)")
        }
    }
    
    // custom functions
    func centerMapLocation(target location: YMKPoint?, map: YMKMapView) {
        guard let location = location else { print("Failed to get user location"); return }
        
        map.mapWindow.map.move(
            with: YMKCameraPosition(target: location, zoom: 18, azimuth: 0, tilt: 0),
            animationType: YMKAnimation(type: YMKAnimationType.smooth, duration: 5)
        )
    }
}

P.S. Чтобы использовать userLocationLayer.setObjectListenerWith(userLocationViewController) создай класс под протокол YMKUserLocationObjectListener

Надеюсь смог помочь.

Подскажите пожалуйста как должен выглядеть класс UserLocationViewController()?

IHIierO avatar Jul 07 '22 11:07 IHIierO

Можно использовать эту библиотеку: https://github.com/aramayyes/YandexMapsSwiftUI

aramayyes avatar Jan 30 '23 14:01 aramayyes