Swift 谷歌地图iOS不允许自定义地图标记图像

Swift 谷歌地图iOS不允许自定义地图标记图像,swift,google-maps,google-maps-markers,google-maps-sdk-ios,google-maps-ios-utils,Swift,Google Maps,Google Maps Markers,Google Maps Sdk Ios,Google Maps Ios Utils,我正在使用iOS版谷歌地图SDK- 结合iOS实用程序库的地图SDK 我正在尝试使用实用程序库在地图上渲染kml文件。它主要起作用,但是标记的自定义图标没有加载。标记及其标题、代码段和位置均正确加载。唯一不起作用的是标记的自定义图标 最初,我认为这是实用程序库的问题,所以我花了一些时间尝试编写自己的代码来遍历kml文件并自己添加自定义标记。然而,在我走得太远之前,我注意到即使我尝试添加一个带有自定义图标的基本标记,我也不能。这让我相信这不是实用程序库的问题,而是iOS版地图SDK的问题。我尝试移

我正在使用iOS版谷歌地图SDK-

结合iOS实用程序库的地图SDK

我正在尝试使用实用程序库在地图上渲染kml文件。它主要起作用,但是标记的自定义图标没有加载。标记及其标题、代码段和位置均正确加载。唯一不起作用的是标记的自定义图标

最初,我认为这是实用程序库的问题,所以我花了一些时间尝试编写自己的代码来遍历kml文件并自己添加自定义标记。然而,在我走得太远之前,我注意到即使我尝试添加一个带有自定义图标的基本标记,我也不能。这让我相信这不是实用程序库的问题,而是iOS版地图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库不起作用,但我确实想出了自己的解决方案。这太可怕了,但我可以在我们完成向应用程序添加所有其他必要功能后回来改进,然后集中精力清理代码

首先,我制作了一个新的地点标记数组,除了地图标记之外,它什么都有。然后,我使用了这个placemarks数组而不是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文件,只为它们选择位置标记和样式,并返回一个标记数组

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文件并修复一些图像名称,但这并不是什么大问题。即使实用程序库工作正常,我也需要这样做,因为实用程序库只处理kml文件,而不处理kmz,因此每个kml文件引用相同的文件夹来处理图像,并使用相同的名称处理图像。很好,每个文件只需要几分钟。如果有一个kmz图书馆就好了,但是哦,好吧


希望这能帮助其他人,希望我能很快找到真正的解决方案(除非实用程序库有问题,希望很快就能解决)

我还没有弄明白为什么utils库不起作用,但我确实想出了自己的解决办法。这太可怕了,但我可以在我们完成向应用程序添加所有其他必要功能后回来改进,然后集中精力清理代码

首先,我制作了一个新的地点标记数组,除了地图标记之外,它什么都有。然后,我使用了这个placemarks数组而不是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文件,只为它们选择位置标记和样式,并返回一个标记数组

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文件并修复一些图像名称,但这并不是什么大问题。即使实用程序库工作正常,我也需要这样做,因为实用程序库只处理kml文件,而不处理kmz,因此每个kml文件引用相同的文件夹来处理图像,并使用相同的名称处理图像。很好,每个文件只需要几分钟。如果有一个kmz图书馆就好了,但是哦,好吧


希望这能帮助其他人,希望我能很快找到真正的解决方案(除非实用程序库有问题,希望很快就能解决)

我应该注意,当我说第二位代码不起作用时,会添加一个带有正确标题的标记,但图标是默认图标,而不是我想要的图标。我还应该注意,第二位代码不起作用的原因是因为我进行了lat和long交换,所以它出现在地图上的不同位置。我觉得很傻,但我们都会犯错误。我应该注意,当我说第二位代码不起作用时,会添加一个带有正确标题的标记,但是图标是默认的,而不是我想要的。还需要注意的是,第二位代码不起作用的原因是因为我进行了lat和long交换,所以它只是出现在地图上的另一个地方。我觉得这很愚蠢,但我们都会犯错误。我不相信这能回答我所问的问题。您编写的代码看起来像是将配置文件图片图像放在当前位置,而不是从kml文件中读入标记和自定义图标并使用该图标。我甚至没有看到你的答案中引用的kml文件。我不相信这回答了我的问题。您编写的代码看起来像是将配置文件图片图像放在当前位置,而不是从kml文件中读入标记和自定义图标并使用该图标。我甚至没有看到你的答案中引用的kml文件。