重复使用的GMSMapView可以在首次使用时使用,但不能在任何其他ViewController上使用

时间:2018-10-27 17:46:34

标签: ios swift google-maps-sdk-ios

我有几个显示地图的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的正确位置,但是从MapViewController继承的任何后续ViewController只会显示UK。

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])中放置一个断点表明第一个ViewController接收了更新的位置,但随后的ViewController没有。

有人可以告诉我我在做什么错吗?

1 个答案:

答案 0 :(得分:1)

由于Schedule Cron expression 0 12 ? * 2 * Next 10 Trigger Date(s) Mon, 29 Oct 2018 12:00:00 GMT Mon, 05 Nov 2018 12:00:00 GMT Mon, 12 Nov 2018 12:00:00 GMT Mon, 19 Nov 2018 12:00:00 GMT Mon, 26 Nov 2018 12:00:00 GMT Mon, 03 Dec 2018 12:00:00 GMT Mon, 10 Dec 2018 12:00:00 GMT Mon, 17 Dec 2018 12:00:00 GMT Mon, 24 Dec 2018 12:00:00 GMT Mon, 31 Dec 2018 12:00:00 GMT 公开了LocationService的一个实例。 CLLocationManager被分配给最后一个要加载的viewController。这就是为什么其他viewController不接收更新的原因。我将使delegate符合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的每个实例将执行相同的工作3次。希望这会有所帮助。