Повторно использованный GMSMapView работает при первом использовании, но не для каких-либо других ViewControllers. - PullRequest
0 голосов
/ 27 октября 2018

У меня есть несколько ViewController, которые отображают карту, поэтому я извлек общую логику карты в MapViewController:

import UIKit
import GoogleMaps
import GooglePlaces

class MapViewController : UIViewController {

var locationService: CLLocationManager!
var placesClient: GMSPlacesClient!
var marker: GMSMarker!
var camera: GMSCameraPosition!
var animatedMarkerImage: UIImage!
var markerImage1: UIImage!
var markerImage2: UIImage!
var markerImage3: UIImage!
var markerImage4: UIImage!
var markerImages: [UIImage]!

@IBOutlet weak var mapView: GMSMapView!

override func viewDidLoad() {
    super.viewDidLoad()

    locationService = LocationService.shared
    placesClient = GMSPlacesClient.shared()

    markerImage1 = UIImage(named: "Location 01@3x")
    markerImage2 = UIImage(named: "Location 02@3x")
    markerImage3 = UIImage(named: "Location 03@3x")
    markerImage4 = UIImage(named: "Location 04v@3x")
    markerImages = [markerImage1, markerImage2, markerImage3, markerImage4]
    animatedMarkerImage = UIImage.animatedImage(with: markerImages, duration: 1.5)

    do {
        if let styleURL = Bundle.main.url(forResource: "mapStyle", withExtension: "json") {
            mapView.mapStyle = try GMSMapStyle(contentsOfFileURL: styleURL)
        } else {
            NSLog("Unable to find mapStyle.json")
        }
    } catch {
        NSLog("One or more of the map styles failed to load. \(error)")
    }
  }
}

extension MapViewController : CLLocationManagerDelegate {


func startReceivingLocationChanges() {
    let authorizationStatus = CLLocationManager.authorizationStatus()

    if authorizationStatus != .authorizedWhenInUse && authorizationStatus != .authorizedAlways {
        return
    }

    if !CLLocationManager.locationServicesEnabled() {
        return
    }

    locationService.desiredAccuracy = kCLLocationAccuracyHundredMeters
    locationService.distanceFilter = 100.0
    locationService.startUpdatingLocation()
}

func locationManager(_ manager: CLLocationManager,  didUpdateLocations locations: [CLLocation]) {
    let location = locations.last!
    if marker == nil {
        camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: 14.0)
        marker = GMSMarker()
        let markerView = UIImageView(image: animatedMarkerImage)

        marker.position = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
        marker.iconView = markerView
        marker.map = mapView
        marker.appearAnimation = GMSMarkerAnimation.pop
        mapView.camera = camera
    } else {
        CATransaction.begin()
        CATransaction.setAnimationDuration(1.0)
        marker.position = location.coordinate
        CATransaction.commit()
    }
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    if let error = error as? CLError, error.code == .denied {
        manager.stopUpdatingLocation()
        return
    }
    print("Location error: \(error)")
  }
}

У меня есть три разных ViewController, которые наследуются от этого MapViewController и переопределяют каждый viewDidLoad() следующим образом:

override func viewDidLoad() {
    super.viewDidLoad()
    locationService.delegate = self
    startReceivingLocationChanges()
}

Карта и маркер отображаются правильно, и камера перемещается в правильное местоположение для первого ViewController, но любой последующий ViewController, который наследуется от MapViewController, просто отображает Великобританию.

Помещение точки останова в func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) показывает, что первый ViewController получает обновленные местоположения, а следующие ViewController - нет.

Может кто-нибудь сказать мне, что я здесь делаю не так?

1 Ответ

0 голосов
/ 29 октября 2018

Поскольку LocationService предоставляет один экземпляр CLLocationManager.Это delegate назначено тому, который был последним загрузчиком viewController.Именно поэтому другие viewControllers не получают обновления.Я бы заставил LocationService соответствовать CLLocationDelegate и установить его делегат себе.Затем добавьте функцию updateLocation к MapViewController, которая обрабатывает обновления карты.

func updateLocation(location: CLLocation){
if marker == nil {
        camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: 14.0)
        marker = GMSMarker()
        let markerView = UIImageView(image: animatedMarkerImage)

        marker.position = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
        marker.iconView = markerView
        marker.map = mapView
        marker.appearAnimation = GMSMarkerAnimation.pop
        mapView.camera = camera
    } else {
        CATransaction.begin()
        CATransaction.setAnimationDuration(1.0)
        marker.position = location.coordinate
        CATransaction.commit()
    }
}

В вашем LocationService обновите контроллеры, вызвав updateLocation

func locationManager(_ manager: CLLocationManager,  didUpdateLocations locations: [CLLocation]) {
    let location = locations.last!
    viewController1.updateLocation(location: location)
    viewController2.updateLocation(location: location)
    viewController3.updateLocation(location: location)
}

Другой способ сделать это - дать каждому MapViewController свой экземпляр CLLocationManager.(не разглашается), но это не реализует вашу идею повторного использования.Поскольку CLLocationManager получает доступ к одной службе определения местоположения на устройстве, каждый экземпляр CLLocationManager будет выполнять одну и ту же работу 3 раза.Надеюсь, это поможет.

...