How to get Marker 's longitude and latitude Swift - swift

I have map view and user can drag marker. When marker tapped, it display snippet that contain location of the marker.
How to get marker's longitude and latitude? if marker is dragged to another position.
Here's what I've done:
var latitude = -7.034323799999999
var longitude = 110.42400399999997
var displayAddress = [String]()
func customizeMap() {
mapView.delegate = self
let camera = GMSCameraPosition.camera(withLatitude: Double(latitude), longitude: Double(longitude), zoom: 17)
mapView.animate(to: camera)
let markerImage = UIImage(named: "ic_home_detail_marker_location")
let markerView = UIImageView(image: markerImage)
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(Double(latitude), Double(longitude))
marker.isDraggable = true
marker.iconView = markerView
marker.snippet = displayAddress[0]
mapView.selectedMarker = marker
marker.map = mapView
}
right now i'm using static longitude and latitude

For that you can use didBeginDragging marker and didEndDragging marker delegates method of GMSMapViewDelegate.
func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) {
print("Drag")
}
func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) {
print("Old Coordinate - \(marker.position)")
}
func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) {
print("New Coordinate - \(marker.position)")
}

Related

Google Maps API didDrag, didBeginDragging, didEndDragging functions do not work

I have set up a single marker on the map view and I am using GMSMapViewDelegate and implementing the following functions:
mapView:didBeginDraggingMarker:
mapView:didEndDraggingMarker:
mapView:didDragMarker:
I have tried reinstalling the pods but nothing I do seems to work. I have been stuck on this problem for the past 5 days and still no luck.
import GoogleMaps
class MapViewController: UIViewController, GMSMapViewDelegate {
let marker = GMSMarker()
var mapView = GMSMapView()
override func viewDidLoad() {
super.viewDidLoad()
// This function fetches data from the server and places marker
makeRequest()
self.marker.isDraggable = true
// Create a map with the location based on user's country
let camera = GMSCameraPosition.camera(withLatitude: defaults.value(forKey: map.lat) as! CLLocationDegrees,
longitude: defaults.value(forKey: map.lon) as! CLLocationDegrees,
zoom: defaults.value(forKey: map.zoom) as! Float)
mapView = GMSMapView.map(withFrame: view.bounds, camera: camera)
}
func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) {
print("DidBeginDragging")
}
func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) {
print("didEndDragging")
}
func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) {
print("didDrag")
}
}
I can drag the marker but I cannot seem to run the three delegate functions.
Looks like you missed setting the delegate:
mapView.delegate = self
at the top change the var mapView = GMSMapView() to var mapView: GMSMapView?
The way you have it, you're creating a mapView and then creating a new one in viewDidLoad
Documentation

Custom infoView for array of markers swift

I have an application where I am working with Googlemaps, I am able to create markers for all the coordinates needed but the issue I am facing now is I want to show a custom UIView when a user taps on a marker to show the info associated with that marker
func showFeaturedProperties(properties: [FeaturedProperties]) {
self.properties = properties
properties.forEach { (props) in
var lat = Double(props.latitude!) as! Double
var lng = Double(props.longitude!) as! Double
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: lat,
longitude: lng)
marker.groundAnchor = CGPoint(x: 0.5, y: 0.5)
marker.isFlat = true
marker.map = mapView
if props.typeId == 1 {
marker.icon = #imageLiteral(resourceName: "_map_rent_icon")
} else {
marker.icon = #imageLiteral(resourceName: "_map_buy_icon")
}
marker.setIconSize(scaledToSize: .init(width: 25, height: 25))
marker.iconView?.contentMode = .scaleAspectFit
self.markers.append(marker)
}
}
The above code shows the marker on the map, how can I show Details when the marker is clicked?
I have so far extended the GMSMapViewDelegate
func mapView(_ mapView: GMSMapView, markerInfoContents marker: GMSMarker) -> UIView? {
if let index = markers.index(of: marker) {
let tappedState = properties[index]
log(tappedState.id)
}
let infoView = BaseCardView()
return infoView
}
this does not work still any help is welcomed
Create infowindow marker view with xib file
import UIKit
import GoogleMaps
class InfoMarkerView: UIView {
var view:UIView!
var parentVC:StartRideViewController?
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
setup()
}
func setup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = UIViewAutoresizing.flexibleWidth
view.autoresizingMask = UIViewAutoresizing.flexibleHeight
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = Bundle(for:type(of: self))
let nib = UINib(nibName: "InfoMarkerView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
func UpdateView(marker:GMSMarker){
// set values to labels here
}
}
Add GMSMapViewDelegate to your viewcontroller file
var mapView: GMSMapView!
var infoMarkerView:InfoMarkerView?
if(latitude != 0 && longitude != 0){
let position = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let marker = GMSMarker(position: position)
var myData = Dictionary<String, Any>()
myData["title"] = ridername
myData["snippet"] = ridertime
myData["photoUrl"] = photoUrl
myData["position"] = position
myData["accuracy"] = accuracy
myData["uid"] = riderUID
myData["status"] = riderStatus
marker.userData = myData
marker.title = ridername
marker.snippet = ridertime
marker.position = position
marker.iconView = self.showImageonMap(imgPath:photoUrl)
marker.map = self.mapView
}
// MARK: GMSMapViewDelegate method implementation
func mapView(_ mapView: GMSMapView!, didTapAt coordinate: CLLocationCoordinate2D) {
print("here")
if infoMarkerView != nil {
infoMarkerView?.removeFromSuperview()
}
}
func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay)
{
print(overlay.zIndex)
print("User Tapped Layer: \(overlay)")
if infoMarkerView != nil {
infoMarkerView?.removeFromSuperview()
}
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
//let update = GMSCameraUpdate.zoom(by: zoomLevel)
//mapView.animate(with: update)
if infoMarkerView != nil {
infoMarkerView?.removeFromSuperview()
}
infoMarkerView = InfoMarkerView(frame: CGRect(x: marker.infoWindowAnchor.x, y: marker.infoWindowAnchor.y, width:180, height: 120))
infoMarkerView?.parentVC = self
// Offset the info window to be directly above the tapped marker
infoMarkerView?.center = mapView.projection.point(for: marker.position)
infoMarkerView?.center.y = (infoMarkerView?.center.y)! - 125
infoMarkerView?.UpdateView(marker: marker)
mapView.addSubview(infoMarkerView!)
return true
}
func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) {
if infoMarkerView != nil {
infoMarkerView?.removeFromSuperview()
}
}
func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
if infoMarkerView != nil {
infoMarkerView?.removeFromSuperview()
}
}

How do I add image overlays to an MKMapView?

----------UPDATED------------
original question at the bottom
I've gotten pretty far, and I have this now:
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet var mapView: MKMapView!
var locationManager: CLLocationManager!
var mapOverlay: MKOverlay!
override func viewDidLoad() {
super.viewDidLoad()
var points = [CLLocationCoordinate2D(latitude: -29.8122, longitude: 148.6351),
CLLocationCoordinate2D(latitude: -27.9307, longitude: 148.6351),
CLLocationCoordinate2D(latitude: -27.9307, longitude: 150.9909),
CLLocationCoordinate2D(latitude: -29.8122, longitude: 150.9909)]
let tile = MKPolygon(coordinates: &points, count: points.count)
tile.title = "zurich"
mapView.addOverlay(tile)
//Setup our Location Manager
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
//Setup our Map View
mapView.delegate = self
mapView.mapType = MKMapType.satellite
mapView.showsUserLocation = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// mapView delegate function
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolygonRenderer(overlay: overlay)
renderer.fillColor = UIColor.red
return renderer
}
}
I now need to know how to replace the renderer.fillColor = UIColor.red with something that will display my image.
Thanks once again
----- original question ------
So, I'm new to Swift and MapKit and I want to add a simple image overlay on top of an MKMapView. I've found a few answers, but they're all confusing, and they are all for Swift 3 and earlier.
I've found that a delegate for the map view is needed, is that a file?
I have already created a map view using the main view controller.
This is what I've done so far (this is in the ViewController.swift file):
import UIKit
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate
{
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
}
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib
let location = CLLocationCoordinate2D(latitude: 47.457925,
longitude: 8.548466)
let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
let region = MKCoordinateRegion(center: location, span: span)
mapView.setRegion(region, animated: true)
}
}
Thank you and I hope you can help!
There are a lot of way to embed image into your maps.
Annotation Views
Callouts
Custom Map Tile
Explain your need more, and maybe we can help better to how to get there.
You are adding overlay over the map. We want to change with specific map tile.
func createLocalUrl(forImageNamed name: String) -> URL? {
let fileManager = FileManager.default
let cacheDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0]
let url = cacheDirectory.appendingPathComponent("\(name).png")
guard fileManager.fileExists(atPath: url.path) else {
guard
let image = UIImage(named: name),
let data = image.pngData()
else { return nil }
fileManager.createFile(atPath: url.path, contents: data, attributes: nil)
return url
}
return url
}
func setupTiles() {
let url = createLocalUrl(forImageNamed: "yourImageName")
let template = url?.absoluteString
let overlay = MKTileOverlay(urlTemplate: template)
overlay.canReplaceMapContent = true
self.tileOverlay = overlay
mapView.addOverlay(overlay)
self.tileRenderer = MKTileOverlayRenderer(tileOverlay: overlay)
}
func isInDesiredArea(middlePoint: MKMapPoint) -> Bool {
//mapView has convert function which converts CGPoint ->
//CLLocationCoordinate2D and vice versa Use this function and,
//Your polygon has boundingMapRect which has contains function.
//Also your map has func mapView(_ mapView: MKMapView,
//regionDidChangeAnimated animated: Bool) which runs whenever region changes..
return myBoundsPolygon.boundingMapRect.hasContain(middlePoint)
}
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
//Convert middle point of your view to CLLocationCoordinate2D
//Convert your coordinate to MKMapPoint
if isInDesiredArea(middlePoint: point) {
setupTiles()
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
....
if overlay is MKTileOverlay {
return tileRenderer
}

GMSMarker has no addGestureRecognizor?

How can I detect if a marker has been clicked on ?
here is my code :
let Meridian = GMSMarker()
Meridian.position = CLLocationCoordinate2D(latitude: 5.654874, longitude: 100.5320142)
Meridian.title = "Recycling Factory"
Meridian.snippet = "Meridian World Sdn Bhd"
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.showMeridianInfo))
Meridian.addGestureRecognizer(tapGesture)//here is where I get the error
#objc func showMeridianInfo (sender: UITapGestureRecognizer) {
print("meradin")
}
you have to conform to GMSMapViewDelegate and implement the:
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {}
within this function you have access to the selected marker details like title and etc.
marker.title

Fill an area in the map with a colour

I've been doing a project in Swift 3.
I choose my points by touching in the map and after that I link them with a line.
I've been trying to fill the area between those points with the color Red but without any success. How can I acomplish this?
I set the fill color, in the mapview, but it isn't working.
I have this code so far:
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet var map: MKMapView!
var points: [CLLocationCoordinate2D] = [CLLocationCoordinate2D]() //all touched points
override func viewDidLoad() {
super.viewDidLoad()
map.delegate = self
let latitude: CLLocationDegrees = 38.925560
let longitude: CLLocationDegrees = -9.229723
let lanDelta: CLLocationDegrees = 0.05
let lonDelta: CLLocationDegrees = 0.05
let span = MKCoordinateSpan(latitudeDelta: lanDelta, longitudeDelta: lonDelta)
let coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let region = MKCoordinateRegion(center: coordinates, span: span)
map.setRegion(region, animated: true)
let uilpgr = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.longpress(gestureRecognizer:)))
uilpgr.minimumPressDuration = 0.5
map.addGestureRecognizer(uilpgr)
}
func longpress(gestureRecognizer: UIGestureRecognizer) {
guard gestureRecognizer.state == .began else { return }
let touchPoint = gestureRecognizer.location(in: self.map)
let coordinate = map.convert(touchPoint, toCoordinateFrom: self.map)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = "My Place"
map.addAnnotation(annotation)
// print("longpress activated")
points.append(annotation.coordinate)
let polyline = MKPolyline(coordinates: points, count: points.count)
map.add(polyline)
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.fillColor = UIColor.red
polylineRenderer.lineWidth = 5
return polylineRenderer
}
}
MKPolyLine will render a line. If you want a filled polygon you need MKPolyon. If you want both an outline and a fill, use both.
fileprivate var polygon: MKPolygon? = nil
func addPolygon() {
let polygon = MKPolygon(coordinates: &polygonCoordinates, count: polygonCoordinates.count)
self.polygon = polygon
mapView.add(polygon)
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let _ = overlay as? MKPolyline {
let renderer = MKPolylineRenderer(polyline: polyLine!)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 2
return renderer
} else {
let renderer = MKPolygonRenderer(polygon: polygon)
renderer.fillColor = UIColor.blue.withAlphaComponent(0.25)
return renderer
}
}