How to Convert GMUFeature to GMSPath - ios

I have drawn slots on google maps using Geojson. Now when the user long presses on the slot should ask the user whether to save the location or not. But I don't know how to enable long press only for the slots. Could anybody suggest me how to do this. Below is the code I have used.
`// the below is the code to render the slots on the google maps
let geoJsonParser = GMUGeoJSONParser(url: url!)
geoJsonParser.parse()
let renderer = GMUGeometryRenderer(map: self.mapview, geometries: geoJsonParser.features)
let style = GMUStyle(styleID: "random", stroke: UIColor.black, fill: UIColor.green, width: 2, scale: 1, heading: 0, anchor: CGPoint(x: 0, y: 0), iconUrl: nil, title: nil, hasFill: true, hasStroke: true)
for feature in geoJsonParser.features {
feature.style = style
}
renderer.render()
// The below code is to check whether the user has long pressed on the slot or not(written this code inside the didLongPressAt function).
for feature in geoJsonParser.features {
if GMSGeometryContainsLocation(coordinate, feature as! GMSPath, true) {// the app is crashing with an error in the console "Could not cast value of type 'GMUFeature' (0x1033573d0) to 'GMSPath' (0x1033585a0)"
print("YES: you are in this polygon.")
marker.title = "\(coordinate)"
marker.map = mapview
} else {
print("You do not appear to be in this polygon.")
}
}`

Finally, after lot of efforts I found the solution.
Note: If anyone is integrating Google-Maps-iOS-Utils library, then don't add header files in Bridging-Header file as suggested in Google developer document.
Wherever you are using the below code, just write import GoogleMapsUtils at top.
let path = Bundle.main.path(forResource: "dld_areas", ofType: "json")
let url = URL(fileURLWithPath: path!)
let data: Data = try! Data.init(contentsOf: url)
let json = try JSON(data: data)
//our json is having properties containing area name and area id, bacause the properties field inside the GMUFeature is retuning us nil, we have to pass it indiviually
let jsonFeatures: [JSON] = json["features"].array ?? []
geoJsonParser = GMUGeoJSONParser.init(data: data)
geoJsonParser.parse()
var index = 0
for feature in geoJsonParser.features {
var innerFeature = feature
while(innerFeature.geometry.type != "GeometryCollection"){
print("type is" + innerFeature.geometry.type)
innerFeature = innerFeature.geometry as! GMUGeometryContainer
}
let collection = innerFeature.geometry as! GMUGeometryCollection
let polygon:GMUPolygon = collection.geometries.first as! GMUPolygon
var isAreaObtained = false
for path in polygon.paths{
//check if the coordinates lie within the polygon
if (GMSGeometryContainsLocation(coordinates, path, true)) {
isAreaObtained = true
print(jsonFeatures[index]["properties"]["NAME_EN"])
print(jsonFeatures[index]["properties"]["AREA_ID"])
print("location inside polygon")
break;
}
}
if(isAreaObtained){
break
}
index = index + 1
}
I found the above code in the following link:
https://github.com/googlemaps/google-maps-ios-utils/issues/205
I have used this code and modified as per my requirement.

Related

Google iOS Cluster Manager "marker.userData" NIL after Cluster/de-Cluster

I am attempting to upgrade my iOS App to use Google Map Clustering.
The App loads over 19,000 markers from a Firebase database using “child added” and I assign an ID to each marker using “marker.userData” as shown below:
dbRef = Database.database().reference()
let markerRef = dbRef.child("markers")
//Load all Markers when app starts
//child added returns all markers, then Listens for new additions
markerRef.observe(.childAdded, with: { [self] snapshot in
markerCount = markerCount+1
let markerKey = snapshot.key
let value = snapshot.value as? NSDictionary
let x = value?["x"] as? Double
let y = value?["y"] as? Double
let v = value?["v"] as? Bool
if v == true {
//print("adding Verifed icon")
let position = CLLocationCoordinate2D(latitude: y ?? 0.0 , longitude: x ?? 0.0)
let marker = GMSMarker(position: position)
marker.icon = UIImage(named: "VerifiedPin")
marker.userData = markerKey
self.markerArray.append(marker)
//print("marker Array: ", self.markerArray)
clusterManager.add(marker)
}else{
//print("adding Unverifed icon")
let position = CLLocationCoordinate2D(latitude: y ?? 0.0 , longitude: x ?? 0.0)
let marker = GMSMarker(position: position)
marker.icon = UIImage(named: "UnverifiedPin")
marker.userData = markerKey
self.markerArray.append(marker)
//print("marker Array: ", self.markerArray)
clusterManager.add(marker)
}
if(markerCount >= numMarkers {
self.clusterManager.cluster()
})
}) { (error:Error) in
print("startObservingDB error: ", error.localizedDescription)
self.noDatabaseConnection()
}
When a user taps on a marker icon “GMSMapView, didTap marker: GMSMarker” is called and if “marker.userData” is not GMUCluster, “marker.userData” should contain the ID assigned when the marker was added to the cluster. This works properly when clustering is not used.
// MARK: - GMSMapViewDelegate
//Detect when user taps on a specific icon and display the infoBox
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
if marker.userData is GMUCluster {
// center the map on tapped marker
viewMap.animate(toLocation: marker.position)
// zoom in on tapped cluster
viewMap.animate(toZoom: viewMap.camera.zoom + 1)
print("Did tap cluster")
return true
}
tappedMarker = marker
let markerKey = marker.userData as! String
print("Did tap marker w/key: ", markerKey)
self.dbRef = Database.database().reference()
self.dbRef.child(markerKey).observeSingleEvent(of: .value, with: { (snapshot: DataSnapshot) in
let areaObj = Area(snapshot: snapshot)
let table = areaObj
print("Table info: ", table)
self.tableMarker = markerKey
print("this is table \(markerKey)")
self.currentTable = table
print (table.verified)
self.lblVerified.isHidden = !table.verified
table.itemRef?.child("verified").observe(.value, with: { (snapshot) in
if let bVerified = snapshot.value as? Bool {
table.verified = bVerified
self.lblVerified.isHidden = !table.verified
}
})
print("source = \(String(describing: table.source))")
print("imported = \(String(describing: table.imported))")
if (table.source != nil) {
self.btnVerify.isHidden = true
} else {
self.btnVerify.isHidden = table.verified
}
self.viewPicDetail.isHidden = false
let formatter = DateFormatter()
if table.lastUpdated == 0.0 {
let defaultDate = "06/30/2018"
formatter.dateFormat = "MM/dd/yyyy"
let date = formatter.date(from: defaultDate)
formatter.locale = Locale(identifier: Locale.preferredLanguages.first!)
formatter.dateStyle = .short
self.lblLastUpdate.text = self.lastUpdateText+"\(formatter.string(from: date!))"
} else {
let date = Date(timeIntervalSince1970: table.lastUpdated)
formatter.locale = Locale(identifier: Locale.preferredLanguages.first!)
formatter.dateStyle = .short
self.lblLastUpdate.text = self.lastUpdateText+"\(formatter.string(from: date))"
}
self.refreshDescription()
self.observeCommentsRatings()
})
return false
}
When the map is first displayed, tapping a marker works properly and the “marker.userData” contains the proper ID. When the map is zoomed-out the markers are clustered and a subsequent zoom-in displays the individual markers. Tapping on a marker after this operation results in a Fatal error: Unexpectedly found nil while unwrapping an Optional meaning that the value of “marker.userData” is “nil”.
It appears that the cluster manager is corrupting “marker.userData” after clustering the markers then “unclustering” them.
Has anyone else seen this issue or am I doing something wrong?
I reported this on the GitHub library issue tracker. The Google development team reproduced the issue, fixed GMUDefaultClusterRenderer.m and released version 3.4.2 of the google-maps-ios-utils library. More information can be found at:
https://github.com/googlemaps/google-maps-ios-utils/issues/349
A big Thanks to the development team for solving this and getting an updated version of the library released quickly.

How to show json data in line chart using swift

I am trying to design an ios app to display json data in a line chart.
First of all, this is my json data.
{
TH_5min: [
{
Data: "2019-02-23T00:00:00",
Time: "11:00:00",
XTP_A: 10.5, //temperature 1
XHP_A: 11.5, //humidity 1
XTP_B: 33.5,
XHP_B: 44.6,
XTP_C: 88.9,
XHP_C: 66.6,
XTP_D: 77.9,
XHP_D: 99.6,
XTP_E: 87.87,
XHP_E: 66.66
},
{
Data: "2019-02-23T00:00:00",
Time: "11:05:00",
XTP_A: 55.2, //temperature 1
XHP_A: 44.3, //humidity 1
XTP_B: 66.6,
XHP_B: 77.87,
XTP_C: 87.77,
XHP_C: 87.87,
XTP_D: 8.87,
XHP_D: 78.78,
XTP_E: 87.78,
XHP_E: 87.87
}
]
}
This is my implementation of the swift code showing json data.
override func viewDidLoad() {
super.viewDidLoad()
apiip = APIip
getlatestTh_5min()
#objc func getlatestTh_5min(){
guard let th_5minUrl = URL(string: "http://" + apiip + "/api/Th_5min") else{
return
}
let request = URLRequest(url: th_5minUrl)
let task = URLSession.shared.dataTask(with: request, completionHandler: {(data,response,error) -> Void in
if let error = error {
print(error)
return
}
if let data = data {
self.th_5mins = self.pardrJsonData(data: data)
self.getchat()
}
})
task.resume()
//getchat()
}
func pardrJsonData(data: Data) -> [Th_5min]{
var th_5mins = [Th_5min]()
do {
let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
let jsonTh_5mins = jsonResult?["TH_5min"] as! [AnyObject]
print(jsonTh_5mins)
print(th_5mins.count)
for jsonTh_5min in jsonTh_5mins{
var th_5min = Th_5min()
th_5min.Data = jsonTh_5min["Data"] as! String
th_5min.Time = jsonTh_5min["Time"] as! String
th_5min.XTP_A = jsonTh_5min["XTP_A"] as! Double
th_5min.XHP_A = jsonTh_5min["XHP_A"] as! Double
print(th_5min)
th_5mins.append(th_5min)
//getchat()
} }catch{
print(error)
}
//getchat()
return th_5mins
}
This is how I draw the line chart, using swift code.
#objc func getchat(){
chartView = LineChartView()
chartView.frame = CGRect(x: 20, y: 80, width: self.view.bounds.width-20,height: self.view.bounds.height-100)
self.view.addSubview(chartView)
var dataEntries1 = [ChartDataEntry]()
for i in 0..<th_5mins.count {
chartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: [th_5mins[i].Time])
let y = th_5mins[i].XTP_A
let entry = ChartDataEntry.init(x: Double(i), y: Double(y))
dataEntries1.append(entry)
}
let chartDataSet1 = LineChartDataSet(entries: dataEntries1, label: "temperature")
chartDataSet1.colors = [NSUIColor.red]
var dataEntries2 = [ChartDataEntry]()
for i in 0..<th_5mins.count {
chartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: [th_5mins[i].Time])
let y = th_5mins[i].XHP_A
let entry = ChartDataEntry.init(x: Double(i), y: Double(y))
dataEntries2.append(entry)
}
let chartDataSet2 = LineChartDataSet(entries: dataEntries2, label: "humidity")
chartDataSet2.colors = [NSUIColor.black]
let chartData = LineChartData(dataSets: [chartDataSet1, chartDataSet2])
chartView.data = chartData
}
}
This is the result of my work.
enter image description here
Although the json data is successfully displayed, I don't know why it is loading for a long time, and I hope that the "time" in my json data can be displayed on the X axis above, marked with my temperature and humidity, and cannot be successful.
I also hope that my line chart view can be implemented as a layout.
"I don't know why it is loading for a long time". Do you mean that the graph does not load immediately upon opening the view? This is because the data is loading asynchronously from a remote source (correctly now, well done). It may well take a few seconds for your JSON to download over the web. That is ok. You can test the endpoint in a browser and see how long the response takes.
"I hope that the 'time' in my json data can be displayed on the X axis above". Yes. You can take the assignation of IndexAxisValueFormatter outside of the loop and you should pass all labels as values into the constructor. Try this code, replacing the equivalent loop:-
var labels: [String] = []
for i in 0..<th_5mins.count {
let y = th_5mins[i].XTP_A
let entry = ChartDataEntry.init(x: Double(i), y: Double(y))
dataEntries1.append(entry)
labels.append(th_5mins[i].Time)
}
chartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: labels)
Note that the method you use for plotting against dates will result in an evenly spread graph, irrespective of your time gaps (e.g. if readings are 5 mins apart between the first two, but 5 years apart for the next two, they will still appear with even gaps between them.

Swift map change points if change SegmentedControl

I'm trying to work with Mapbox.
I have created a point on my map and show from file
I want that when SegmentedControl is changed, item.type is changed accordingly and get correct data
For example if press 0 case -> make 0 == item.type
I create custom points
func addItemsToMap(features: [MGLPointFeature]) {
guard let style = mapView.style else { return }
let source = MGLShapeSource(identifier: "mapPoints", features: features, options: nil)
style.addSource(source)
let colors = [
"black": MGLStyleValue(rawValue: UIColor.black)
]
let circles = MGLCircleStyleLayer(identifier: "mapPoints-circles", source: source)
circles.circleColor = MGLSourceStyleFunction(interpolationMode: .identity,
stops: colors,
attributeName: "color",
options: nil)
circles.circleRadius = MGLStyleValue(interpolationMode: .exponential,
cameraStops: [2: MGLStyleValue(rawValue: 5),
7: MGLStyleValue(rawValue: 8)],
options: nil)
circles.circleStrokeWidth = MGLStyleValue(rawValue: 2)
circles.circleStrokeColor = MGLStyleValue(rawValue: UIColor.white)
style.addLayer(circles)
}
Put data to mapbox
func test(number: Int) {
guard let documentsDirectoryUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let urlBar = documentsDirectoryUrl.appendingPathComponent("Persons.json")
do {
let jsonData = try Data(contentsOf: urlBar)
//Переводим их в модель
let result = try JSONDecoder().decode(CollectionTest.self, from: jsonData)
let coll: CollectionTest = result
let features = parseJSONItems(collection: coll, number: number)
addItemsToMap(features: features)
print(features)
} catch { print("Error while parsing: \(error)") }
}
Get data from file
func parseJSONItems(collection: CollectionTest, number: Int) -> [MGLPointFeature] {
var features = [MGLPointFeature]()
for item in collection.prices {
if item.type == number {
...get data to annotation and location
let feature = MGLPointFeature()
feature.coordinate = coordinate
feature.title = "\(name)"
feature.attributes = [
"color" : color,
"name" : "\(name)"
]
features.append(feature)
}
}
}}}
}
return features
}
I need to change number from 0 to 4, because in data I have type from 0 to 4 and points need to change from 0-4 if SegmentedControl is changed
in SegmentedControl I have
#objc func change(sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case 0:
test(number: 0)
case 1:
test(number: 1)
case 2:
ttest(number: 2)
case 3:
test(number: 3)
case 4:
test(number: 4)
default:
test(number: 2)
}
}
In viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
styleToggle.addTarget(self, action: #selector(change(sender:)), for: .valueChanged)
test(number: 2)
}
When app run - works good and show all data == type 2
But when I change button in SegmentedControl to case 0 or others - I get a crash and in console prints
Terminating app due to uncaught exception
'MGLRedundantSourceIdentifierException', reason: 'Source mapPoints already exists'
What am I doing wrong? How to fix this?
It looks like you are trying to add a source to your map that already exists. In order to avoid this message, you will want to either:
Check for the existence of a source before adding it to your style. In your use case, maybe name your sources mapPoints-circles-\(number). If the source already exists, reuse it.
Add the source to the map one time (preferably within the initial -mapView:didFinishLoadingStyle:). In order to create new layers from it layer, you can access the source from the map's style.
If the points come from a source with an identifier my-source, you would try:
guard let source = style.source(withIdentifier: "my-source") else { return }
when clicking a segment, remove all markers which are already present in the map
then add new markers
You can use map.removeLayer(marker); to remove the marker (an ILayer object).

Maps Direction Line doesn't showing up on Maps

On trying to give direction line between User location to defined location. The pinpoints were right and exactly at the desired location but there is no 'Line' direction which leads User location to defined location.
It was done like this image:
and my code for drawing the maps along with parsing google maps API JSON:
func DrawDirection(url: String, cord: CLLocationCoordinate2D){
request(url).responseJSON { response in
let parsed = try? JSONSerialization.jsonObject(with: response.data!, options: []) as! [String:Any]
let routes = parsed!["routes"] as! [[String:Any]]
for route in routes {
let dictArr = route["legs"] as? [[String:Any]]
let dict = dictArr![0]["steps"] as? [[String:Any]]
let start = dict![0]["start_location"] as? [String:Any]
let lat = start!["lat"] as! Double
let long = start!["lng"] as! Double
let dotcoordinate = CLLocationCoordinate2D(latitude: CLLocationDegrees(lat), longitude: CLLocationDegrees(long))
let routePoly = route["overview_polyline"] as! [String:Any]
let points = routePoly["points"] as! String
let line = points
DispatchQueue.main.async {
let bounds = GMSCoordinateBounds(coordinate: cord, coordinate: dotcoordinate)
let update = GMSCameraUpdate.fit(bounds, with: UIEdgeInsetsMake(170, 30, 30, 30))
self.CinemaLoc.moveCamera(update)
}
self.AddingPolyLine(encString: line, dir: cord, dot: dotcoordinate)
}
}
}
func AddingPolyLine(encString: String, dir: CLLocationCoordinate2D, dot: CLLocationCoordinate2D){
let dotpath: GMSMutablePath = GMSMutablePath()
dotpath.add(CLLocationCoordinate2DMake(dir.latitude, dir.longitude)) //original loc
dotpath.add(CLLocationCoordinate2DMake(dot.latitude, dot.longitude)) //starting points
let dotpoly = GMSPolyline(path: dotpath)
dotpoly.map = self.CinemaLoc
dotpoly.strokeWidth = 3.0
let styles:[Any] = [GMSStrokeStyle.solidColor(.blue), GMSStrokeStyle.solidColor(.clear)]
let lengths:[Any] = [10,5]
dotpoly.spans = GMSStyleSpans(dotpoly.path!,styles as!
[GMSStrokeStyle], lengths as! [NSNumber], GMSLengthKind.rhumb)
let poly = GMSPolyline(path: dotpath)
poly.strokeWidth = 3.0
poly.strokeColor = .red
poly.map = self.CinemaLoc
}
cord is User location
been trying all possible way on stack overflow but not getting any change and sometimes there are log saying "Failed to load optimized model at path ~/GoogleMaps.bundle/GMSCacheStorage.momd/"
is there any wrong with my code?
Path should be created only once, for a specific path, and then you can add coordinates to the path. You're doing wrong by putting let dotpath: GMSMutablePath = GMSMutablePath() inside your method call, which gets called for every loop.
Sorry guys, problem fixed. there are misplaced on my url. and for adding polyline should be like this
let path = GMSMutablePath(fromEncodedPath: "String from overview json")
let poly = GMSPolyline(path: dotpath)
poly.strokeWidth = 3.0
poly.strokeColor = .red
poly.map = self.CinemaLoc
On routes loop, it should be no problem since google maps api only give 1 array of route, but for better practice. It should out of loop
Thank you and happy coding!

Some markers wont go away in Google Maps using iOS and Swift

I hope someone can help me find this out, I have this problem since yesterday and have been searching what could be wrong, maybe I missed something? I'm new (about 2 months using a mac) to iOS and Swift and the whole mac ecosystem in general.
The thing is that I'm migrating to native iOS an Phonegap app that relies on a lot of markers (about 300 to 400, and lags a lot) that some of them can be disabled by the user(by groups), the problem comes when deleting the markers some of them remain like ghosts, their map property is set to nil, and no touch event is triggered(I've got them set to perform a segue)
Here is the code that I use to store the objects, and then to delete them, currently I'm using a dictionary with arrays to determine which markers to delete.
I translated the comments because they are in Spanish so you can have an idea of what i'm doing (or trying to do) in short terms.
Here is the code where I add the markers, also I know that there might be some better ways to do some things like
//parses some data, and retrieves some more to create the markers
func procesaMarcadores(retorno: [String:Any]) {
//skiped a lot of previous code
if let servicios = retorno["servicios"] as? NSArray {
//a simple cycle to iterate through data recieved
for item in servicios {
let items = item as! NSDictionary
//lazy, easy, and dirty way to retrieve latitude and longitude, must change
let latitud = (items["direccion_georeferenciada_latitud"] as! NSString).doubleValue
let longitud = (items["direccion_georeferenciada_longitud"] as! NSString).doubleValue
let foto = self.urlFotos + String((items["foto"] as! NSString))
//new marker
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: latitud, longitude: longitud)
marker.userData = foto //a simple string with a url to use latter in the next view
//setting mapView in main thread just for safety?, don't wanna mess something
DispatchQueue.main.async(){
marker.map = self.mapView
}
marker.icon = imagenChica //custom marker image
//storing the objects in dictionary
let tipo = items["id_tipo_servicio"] as! Int
var arregloServicios = dicServicios[tipo] ?? []
arregloServicios.append(marker)
dicServicios[tipo] = arregloServicios
}
}
}
Here I delete the markers
//updates markers, gets new data for markers, and deletes markers
func actualizaMarcadores(marcadores: [Any]?, seleccionado: Int, perfil: Int?){
//lots of deleted code
//deletes markers group if variable noSale is set to delete markers of the group of the variable seleccionado
if noSale {
//asynchronous delete just to be safe?
DispatchQueue.main.async {
//whiping markers from mapView
var arregloServicios = self.dicServicios[seleccionado]
for i in arregloServicios! {
i.map = nil
}
//releasing a bit of memory
self.dicServicios[seleccionado] = nil
//already tried not deleting the marker objects
}
}
}
I have googled for the answer and I have been researching and found nothing relevant, other than that some years ago, in an old google maps api had a bug, but it was fixed, also searched in the documentation but the only thing I found was that the other way to delete markers is with mapView.clear() but then i would have to reassign all the markers and the cpu goes to about 60% and thats worst than about 5% cpu usage with some poorly coded ways to cast string to int.
Here I give you just overview you can cross check it with your existing code
import GoogleMaps
var arrayMarkerObj = [String:GMSMarker]() //Use dictionary
var driverMarker:GMSMarker! //Define it as gloabal
class markerController:UIViewController{
func procesaMarcadores(retorno: [String:Any]) {
//skiped a lot of previous code
if let servicios = retorno["servicios"] as? NSArray {
//a simple cycle to iterate through data recieved
for item in servicios {
let items = item as! NSDictionary
//lazy, easy, and dirty way to retrieve latitude and longitude, must change
let latitud = (items["direccion_georeferenciada_latitud"] as! NSString).doubleValue
let longitud = (items["direccion_georeferenciada_longitud"] as! NSString).doubleValue
let foto = self.urlFotos + String((items["foto"] as! NSString))
//new marker
let positionDriver = CLLocationCoordinate2DMake(latitude: latitud, longitude: longitud)
var marker:GMSMarker! = GMSMarker(position: positionDriver)
marker.userData = foto //a simple string with a url to use latter in the next view
//setting mapView in main thread just for safety?, don't wanna mess something
// DispatchQueue.main.async(){
// marker.map = self.mapView
// }
marker.icon = imagenChica //custom marker image
marker.map = self.mapView
self.arrayMarkerObj.updateValue(marker, forKey: key) //Put some uniqe KEY which define marker location
self.animateMarker(objMarker: marker, locations: positionDriver)
//storing the objects in dictionary
// let tipo = items["id_tipo_servicio"] as! Int
// var arregloServicios = dicServicios[tipo] ?? []
// arregloServicios.append(marker)
// dicServicios[tipo] = arregloServicios
}
}
}
func animateMarker(objMarker:GMSMarker,locations:CLLocationCoordinate2D){
CATransaction.begin()
CATransaction.setAnimationDuration(2.0)
objMarker.position = locations
CATransaction.commit()
}
//Delete Marker
func deleteMark(){
for(key, value) in self.arrayMarkerObj{
self.driverMarker = self.arrayMarkerObj[key!]
if(self.driverMarker != nil){
self.driverMarker.map = nil
self.arrayMarkerObj.removeValue(forKey: key!)
}
}
}
}

Resources