Google 地图 iOS 不允许自定义地图标记图像

Google Maps iOS is not allowing custom map marker image

我正在为 iOS 使用 Google Maps SDK - https://developers.google.com/maps/documentation/ios-sdk/marker#use_the_markers_icon_property

与 iOS 实用程序库的 Maps SDK 相结合 https://developers.google.com/maps/documentation/ios-sdk/utility/kml-geojson#render-kml-data

我正在尝试使用实用程序库在地图上渲染 kml 文件。它主要工作,但未加载标记的自定义图标。带有标题、片段和位置的标记都可以正确加载。唯一不起作用的是标记的自定义图标。

最初,我认为这是实用程序库的问题,所以我花了一些时间尝试编写自己的代码来遍历 kml 文件并自己添加自定义标记。然而,在我走得太远之前,我注意到即使我尝试添加带有自定义图标的基本标记,我也做不到。这让我相信这不是实用程序库的问题,而是 iOS 的 Maps SDK 的问题。我试过移动图像所在的文件夹,并确保代码可以看到图像的路径,但我无法让它工作。

这是我项目中的代码

let path = Bundle.main.path(forResource: testFile, ofType: "kml")
let url = URL(fileURLWithPath: path!)
let kmlParser = GMUKMLParser(url: url)
kmlParser.parse()

let camera = GMSCameraPosition.camera(withLatitude: lat, longitude: long, zoom: zoom)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView.mapType = GMSMapViewType.terrain
mapView.isMyLocationEnabled = true
mapView.settings.zoomGestures = true
mapView.settings.myLocationButton = true

let renderer = GMUGeometryRenderer(map: mapView, geometries: kmlParser.placemarks, styles: kmlParser.styles, styleMaps: kmlParser.styleMaps)
renderer.render()

这也不行

let position = CLLocationCoordinate2D(latitude: lat, longitude: long)
let marker = GMSMarker(position: position)
marker.title = "Test"
marker.icon = UIImage(named: "icon-1")
marker.map = mapView

在此先感谢您的帮助

我还没有弄清楚为什么 utils 库不起作用,但我确实想出了我自己的修复方法。这太可怕了,但我可以在我们完成向应用程序添加所有其他必要功能并可以专注于清理代码后回来改进它。

首先,我制作了一个新的地标数组,除了地图标记外,它什么都有。然后我使用这个地标数组而不是 kmlParser.placemarks,以便实用程序库可以添加其他所有内容。

//Removing markers without icons
var myIndex = 0
var removed = [GMUGeometryContainer]()
for mark in kmlParser.placemarks{
    if(mark.geometry.type != "Point"){
         removed.append(kmlParser.placemarks[myIndex])
    }
    myIndex += 1
}

let renderer = GMUGeometryRenderer(map: mapView, geometries: removed, styles: kmlParser.styles, styleMaps: kmlParser.styleMaps)
renderer.render() 

在那之后,我做了我自己的可怕的可怕方法,再次读取 kml 文件,并且只为它们挑选出地标和样式以及 returns 一组标记。

func addMarkers(fileName:String) -> [GMSMarker]{
    var markers = [GMSMarker]()
    if let path = Bundle.main.path(forResource: fileName, ofType: "kml"){
        do{
            let data = try String(contentsOfFile: path, encoding: .utf8)
            let myStrings = data.components(separatedBy: .newlines)
            var styleToIcon = [String: String]()

            var lineNum = 0
            for line in myStrings{
                //Detecting new style that will be used in placemarks
                if line.contains("Style id") && line.contains("normal") && !line.contains("line-"){
                    let newKey = String(line.split(separator: "\"")[1])
                    let newValue = String(myStrings[lineNum+4].split(separator: ">")[1].split(separator: "/")[1].split(separator: "<")[0])
                    styleToIcon[newKey] = newValue
                }

                //Detecting new placemark on map
                else if(line.contains("<Placemark>") && !myStrings[lineNum+2].contains("#line")){
                    //Get name
                    var name = myStrings[lineNum+1].split(separator: ">")[1].split(separator: "<")[0]
                    //Sometimes name has weird CDATA field in it that needs to be removed
                    if(name.contains("![CDATA")){
                        name = name.split(separator: "[")[2].split(separator: "]")[0]
                    }

                    //Get snippet (description)
                    var snippet = myStrings[lineNum+2].split(separator: ">")[1].split(separator: "<")[0]
                    //Sometimes snippet has weird CDATA field in it that needs to be removed
                    if(snippet.contains("![CDATA")){
                        snippet = snippet.split(separator: "[")[2].split(separator: "]")[0]
                    }

                    //Get style
                    let style = String(myStrings[lineNum+3].split(separator: ">")[1].split(separator: "#")[0].split(separator: "<")[0] + "-normal")

                    //Get Coordinates
                    let coordStringSplit = myStrings[lineNum+6].split(separator: ",")
                    var lat = 0.0
                    var long = 0.0
                    if(coordStringSplit[0].contains("-")){
                        long = Double(coordStringSplit[0].split(separator: "-")[1])! * -1.0
                    }else{
                        long = Double(coordStringSplit[0])!
                    }
                    if(coordStringSplit[1].contains("-")){
                        lat = Double(coordStringSplit[1].split(separator: "-")[1])! * -1.0
                    }else{
                        lat = Double(coordStringSplit[1])!
                    }

                    //Create marker and add to list of markers
                    let position = CLLocationCoordinate2D(latitude: lat, longitude: long)
                    let marker = GMSMarker(position: position)
                    marker.title = String(name)
                    marker.snippet = String(snippet)
                    marker.icon = UIImage(named: styleToIcon[style]!)
                    markers.append(marker)
                }
                lineNum += 1
            }
        }catch{
            print(error)
        }
    }
    return markers
}

这与我的 kml 文件的外观密切相关,我怀疑它是否会对其他人有所帮助,但我认为我应该 post 它以防万一。

现在我们有了那个方法,我们需要做的就是回到我们渲染所有 kml 数据的地方并在地图上渲染这些标记

//Adding markers with icons
let newMarkers = addMarkers(fileName: courseName)
for mark in newMarkers{
    mark.map = mapView
}

我还必须手动检查我的 kml 文件并修复一些图像名称,但这不是什么大问题。即使实用程序库有效,我也需要这样做,因为实用程序库只处理 kml 文件而不处理 kmz,因此每个 kml 文件引用相同的图像文件夹并使用相同的图像名称。很好,每个文件只需要几分钟。如果有一个 kmz 图书馆就好了,但是哦,好吧。

希望这对其他人有帮助,并希望我能尽快找到真正的解决方案(除非它是实用程序库的问题,在这种情况下希望它能尽快修复)。

//call method by passing ;

 if userLocation.coordinate.latitude != 0.0 && userLocation.coordinate.longitude != 0.0
  {
               self.updateCurrentPositionMarker(currentLocation: CLLocation(latitude: userLocation.coordinate.latitude, longitude:userLocation.coordinate.longitude))

  }


//methods


func updateCurrentPositionMarker(currentLocation: CLLocation) {
        self.currentPositionMarker.map = nil
        self.currentPositionMarker = GMSMarker(position: currentLocation.coordinate)

        if self.imageDataUrl != ""
        {

            let camera: GMSCameraPosition = GMSCameraPosition.camera(withLatitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude, zoom: 18.0)
            self.mapView.camera = camera

//self.imageDataUrl  == image to show

            self.currentPositionMarker.iconView = self.drawImageWithProfilePic(urlString:self.imageDataUrl,image: UIImage.init(named: “backgroungImage”)!)

            self.currentPositionMarker.zIndex = 1

        }

        self.currentPositionMarker.map = self.mapView

        self.mapView.reloadInputViews()
    }




    func drawImageWithProfilePic(urlString:String, image: UIImage) -> UIImageView {

        let imgView = UIImageView(image: image)
        imgView.frame = CGRect(x: 0, y: 0, width: 90, height: 90)

        let picImgView = UIImageView()
        picImgView.sd_setImage(with:URL(string: urlString))
        picImgView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
        imgView.addSubview(picImgView)

        picImgView.center.x = imgView.center.x
        picImgView.center.y = imgView.center.y-10
        picImgView.layer.cornerRadius = picImgView.frame.width/2
        picImgView.clipsToBounds = true
        imgView.setNeedsLayout()
        picImgView.setNeedsLayout()

//        let newImage = imageWithView(view: imgView)
//        return newImage

        return imgView
    }