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

时间:2019-07-03 21:51:48

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

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

与iOS工具库https://developers.google.com/maps/documentation/ios-sdk/utility/kml-geojson#render-kml-data的Maps SDK结合

我正在尝试使用实用程序库在地图上呈现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

在此先感谢您的帮助

2 个答案:

答案 0 :(得分:0)

我还没有弄清楚为什么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文件,并且仅为其选择地标和样式,并返回一组Markers。

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数据并在地图上渲染这些标记的地方

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

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

希望这对其他人有帮助,希望我能尽快找到真正的解决方案(除非它与实用程序库有关,在这种情况下希望很快就可以解决)。

答案 1 :(得分:0)

private fun getUpdatedContacts(): Cursor? {

    val projection = arrayOf(
            ContactsContract.Contacts._ID,
            ContactsContract.Contacts.DISPLAY_NAME,
            ContactsContract.Contacts.HAS_PHONE_NUMBER,
            ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP)

    val selection = ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " > ? AND " +
            ContactsContract.Contacts._ID + "<= ?"

    val selectionArgs = arrayOf(mFireContactDetails!!.lcu_ms.toString(), mFireContactDetails!!.lcid.toString())

    val sortOrder = ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " ASC"

    return mContentResolver.query(
            ContactsContract.Contacts.CONTENT_URI,
            projection,
            selection,
            selectionArgs,
            sortOrder)
}