Trying to get additional information from Map Annotations-swift - iphone

I am trying to make a simple app that has a map and some fixed annotations. I want to click those annotations, their button, and get a menu with a picture and some additional text like how the Apple Maps points work.
So far here is my code, I can get all the way to the DetailDisclosure Button, but I cannot get it to work that way when I click it. Can someone help me? Thanks in advance.
(there is also a class called Shops, but I haven't included in this post)
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, UIPopoverPresentationControllerDelegate{
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
var mapItemData:MKMapItem!
override func viewDidLoad() {
super.viewDidLoad()
// Initiate GPS
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
//Pin coordinates
mapView.delegate = self
let J = Shops(title: "Jingle", coordinate: CLLocationCoordinate2D(latitude: 44.631076, longitude: 22.946770), info: "H", address:"Π", subtitle:"κ")
let K = Shops(title: "R", coordinate: CLLocationCoordinate2D(latitude: 43.65, longitude: 6.43), info: "F", address:"Π", subtitle:"κ")
let L = Shops(title: "P", coordinate: CLLocationCoordinate2D(latitude: 58.89, longitude: 2.3508), info: "O", address:"Π", subtitle:"κ")
let B = Shops(title: "R", coordinate: CLLocationCoordinate2D(latitude: 26, longitude: 17), info: "H", address:"Π", subtitle:"κ")
let W = Shops(title: "W", coordinate: CLLocationCoordinate2D(latitude: 88.43111, longitude: -37.035663), info: "N", address:"Π", subtitle:"κ")
mapView.addAnnotations([J, K, L, B, W])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Locate through GPS
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1))
self.mapView.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "Shops"
if annotation.isKindOfClass(Shops.self) {
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
let btn = UIButton(type: .InfoLight)
annotationView!.rightCalloutAccessoryView = btn
}else{
annotationView!.annotation = annotation
}
return annotationView
}
return nil
}
//Zoom out to enclose all annotations
func fitMapViewToAnnotaionList(annotations: [MKPointAnnotation]) -> Void {
let mapEdgePadding = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
var zoomRect:MKMapRect = MKMapRectNull
for index in 0..<annotations.count {
let annotation = annotations[index]
let aPoint:MKMapPoint = MKMapPointForCoordinate(annotation.coordinate)
let rect:MKMapRect = MKMapRectMake(aPoint.x, aPoint.y, 0.1, 0.1)
if MKMapRectIsNull(zoomRect) {
zoomRect = rect
} else {
zoomRect = MKMapRectUnion(zoomRect, rect)
}
}
mapView.setVisibleMapRect(zoomRect, edgePadding: mapEdgePadding, animated: true)
}
}

Related

add go button MapKit Swift

I am using MapKit. It draws the route between the two entered locations. But the go button does not appear. So he draws the route but doesn't describe how to go on the route. You can see in the photo. It puts the pins, but the Go to route button does not appear. How can I activate the go button?
class customPin: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
init(pinTitle:String, pinSubTitle:String, location:CLLocationCoordinate2D) {
self.title = pinTitle
self.subtitle = pinSubTitle
self.coordinate = location
}
}
class mapViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let sourceLocation = CLLocationCoordinate2D(latitude:39.173209 , longitude: -94.593933)
let destinationLocation = CLLocationCoordinate2D(latitude:38.643172 , longitude: -90.177429)
let sourcePin = customPin(pinTitle: "Kansas City", pinSubTitle: "aa", location: sourceLocation)
let destinationPin = customPin(pinTitle: "St. Louis", pinSubTitle: "ddd", location: destinationLocation)
self.mapView.addAnnotation(sourcePin)
self.mapView.addAnnotation(destinationPin)
let sourcePlaceMark = MKPlacemark(coordinate: sourceLocation)
let destinationPlaceMark = MKPlacemark(coordinate: destinationLocation)
let directionRequest = MKDirections.Request()
directionRequest.source = MKMapItem(placemark: sourcePlaceMark)
directionRequest.destination = MKMapItem(placemark: destinationPlaceMark)
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate { (response, error) in
guard let directionResonse = response else {
if let error = error {
print("we have error getting directions==\(error.localizedDescription)")
}
return
}
let route = directionResonse.routes[0]
self.mapView.addOverlay(route.polyline, level: .aboveRoads)
let rect = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegion(rect), animated: true)
}
self.mapView.delegate = self
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 4.0
return renderer
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Trying to pass annotation from one view controller to another

I am viewing a location on my first view controller. I want to also view the same location on a second view controller. How can I pass the location on the first view controller to the second view controller? or Trying to pass annotation from one view controller to another?
import UIKit
import Foundation
import MapKit
import CoreLocation
class FirstViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate, MKMapViewDelegate {
//Map
#IBOutlet weak var Map: MKMapView!
let manager = CLLocationManager()
var directionsArray: [MKDirections] = []
//user location constanatly updates
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
//my location coordinates????
let myLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude,location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegion(center: myLocation, span: span)
Map.showsScale = true
Map.showsPointsOfInterest = true
Map.setRegion(region, animated: true)
self.Map.showsUserLocation = true
}
// Search Button functions
#IBAction func SearchButton(_ sender: Any)
{
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.delegate = self
present(searchController, animated: true, completion: nil)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
//Ignoring user
UIApplication.shared.beginIgnoringInteractionEvents()
//Activity Indicator
let activityIndicator = UIActivityIndicatorView()
activityIndicator.style = UIActivityIndicatorView.Style.gray
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.startAnimating()
self.view.addSubview(activityIndicator)
//hide search bar
searchBar.resignFirstResponder()
dismiss(animated: true, completion: nil)
//Create the search request
let searchRequest = MKLocalSearch.Request()
searchRequest.naturalLanguageQuery = searchBar.text
let activeSearch = MKLocalSearch(request: searchRequest)
activeSearch.start{ (response, error) in
activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
if response == nil
{
print("Error")
}
else
{
//Remove annotations
let annotations = self.Map.annotations
self.Map.removeAnnotations(annotations)
//Getting Data
let latitude = response?.boundingRegion.center.latitude
let longitude = response?.boundingRegion.center.longitude
//Create annotation
let annotation = MKPointAnnotation()
annotation.title = searchBar.text
//annotation.coordinate = locationManager.location!.coordinate
annotation.coordinate = CLLocationCoordinate2DMake(latitude!, longitude!)
self.Map.addAnnotation(annotation)
//Zooming in annotation
let coordinate:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude!, longitude!)
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
let region = MKCoordinateRegion(center: coordinate,span: span)
self.Map.setRegion(region, animated: true)
let sourceCoordinates = self.manager.location?.coordinate
let destinationCoodinates = CLLocationCoordinate2DMake(latitude!, longitude!)
let sourcePlacemark = MKPlacemark(coordinate: sourceCoordinates!)
let destPlacemark = MKPlacemark(coordinate: destinationCoodinates)
let sourceItem = MKMapItem(placemark: sourcePlacemark)
let destItem = MKMapItem(placemark: destPlacemark)
let directionsRequest = MKDirections.Request()
directionsRequest.source = sourceItem
directionsRequest.destination = destItem
directionsRequest.transportType = .automobile
let directions = MKDirections(request: directionsRequest)
directions.calculate(completionHandler: { response, error in
guard let response = response else {
if let error = error {
print("Something Went Wrong")
}
return
}
// reset/clear prevous search route
resetMapView(withNew: directions)
// display single best route on map with a polyline
let route = response.routes[0]
self.Map.addOverlay(route.polyline, level: .aboveRoads)
// animate/draw route on map
let rekt = route.polyline.boundingMapRect
self.Map.setRegion(MKCoordinateRegion(rekt),animated: true)
})
//function removes current route on map
func resetMapView(withNew directions: MKDirections){
self.Map.removeOverlays(self.Map.overlays)
self.directionsArray.append(directions)
let _ = self.directionsArray.map { $0.cancel() }
}
}
}
}
//******************************************************************************************
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
// function displays route on map
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 5.0
return renderer;
}
}
// Second View controller code below
import UIKit
import Foundation
import MapKit
import CoreLocation
class SecondViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate, MKMapViewDelegate {
#IBOutlet weak var Map2: MKMapView!
let manager = CLLocationManager()
var directionsArray: [MKDirections] = []
//************************************************************
//user location constanatly updates
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
// my location coordinates
let myLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude,location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegion(center: myLocation, span: span)
Map2.showsScale = true
Map2.showsPointsOfInterest = true
Map2.setRegion(region, animated: true)
self.Map2.showsUserLocation = true
}
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
// function displays route on map
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 5.0
return renderer;
}
}

Map Annotation Callout Title

I was using MapKit and have shown five points of location and the pins are coming too. Now, I want to get a callout when I press on the pin annotation. How can I get that?
Here is the code:
class MultipleAnnotationController: UIViewController {
let sec22 = Capital(title: "Sector 22", coordinate: CLLocationCoordinate2D(latitude: 30.7339583, longitude: 76.77261969999995), info: "Sector 22 Aroma")
let sec34 = Capital(title: "Sector 34", coordinate: CLLocationCoordinate2D(latitude: 30.7195549, longitude: 76.76394989999994), info: "Aakash Institute")
let mohali = Capital(title: "Mohali Office", coordinate: CLLocationCoordinate2D(latitude: 30.707318902730268, longitude: 76.70382329676794), info: "Office Location")
let rmalerkotla = Capital(title: "Malerkotla Home", coordinate: CLLocationCoordinate2D(latitude: 30.5232076, longitude: 75.88825079999992), info: "Home")
let delhi = Capital(title: "New Delhi", coordinate: CLLocationCoordinate2D(latitude: 28.7040592, longitude: 77.10249019999992), info: "Capital of India")
#IBOutlet weak var mapV: MKMapView!
override func viewDidLoad() {
mapV.addAnnotations([sec22, sec34, mohali, rmalerkotla, delhi])
super.viewDidLoad()
}
class Capital: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
var info: String
init(title: String, coordinate: CLLocationCoordinate2D, info: String) {
self.title = title
self.coordinate = coordinate
self.info = info
}
}
}
You need to implement the following method,
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "Pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.canShowCallout = true
}
else {
pinView?.annotation = annotation
}
return pinView
}
Don't forget to set mapV.delegate.
override func viewDidLoad() {
super.viewDidLoad()
mapV.addAnnotations([sec22, sec34, mohali, rmalerkotla, delhi])
mapV.delegate = self
}

Route Between two A and B location

There is no error but I can not get the location from my current location to what I search. Can someone please help. It says this with I click on the Car logo to get directions: MKDirectionsErrorCode=7, NSLocalizedDescription=Directions Not Available}
I am only missing the line to get to the direction. When I click on the car logo, it just does not do anything but zoom out to my current location. I am missing anything or did something wrong?
Here is my code:
protocol HandleMapSearch {
func dropPinZoomIn(placemark:MKPlacemark)
}
class ViewController: UIViewController {
#IBOutlet weak var mapView: MKMapView! // Handle the Map Kit View
var selectedPin:MKPlacemark? = nil //Any incoming placemarks
// Destination for directions*********
var destination:MKMapItem = MKMapItem()
var MyPosition = CLLocationCoordinate2D()
var resultSearchController:UISearchController? = nil // Keep the UISearchController in memory after it's created
var locationManager = CLLocationManager() // Core Location
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest // Accuracy level
locationManager.requestWhenInUseAuthorization() // Triggers the location permission dialog
locationManager.startUpdatingLocation()
//locationManager.requestLocation() // Trigers a one-time location request
// Set up the search results table
let locationSearchTable = storyboard!.instantiateViewController(withIdentifier: "LocationSearchTable") as! LocationSearchTable
resultSearchController = UISearchController(searchResultsController: locationSearchTable)
resultSearchController?.searchResultsUpdater = locationSearchTable
// Set up the search bar
let searchBar = resultSearchController!.searchBar
searchBar.sizeToFit()
searchBar.placeholder = "Search for places"
navigationItem.titleView = resultSearchController?.searchBar
// Configure the UISearchController appearance
resultSearchController?.hidesNavigationBarDuringPresentation = false
resultSearchController?.dimsBackgroundDuringPresentation = true
definesPresentationContext = true
locationSearchTable.mapView = mapView // Passes along a handle of the mapView
locationSearchTable.handleMapSearchDelegate = self // Handles the map search
}
//Getting direction of location
#objc func getDirections(sender: AnyObject){
if let selectedPin = selectedPin {
let mapItem = MKMapItem(placemark: selectedPin)
//let launchOptions = [MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving]
//mapItem.openInMaps(launchOptions: launchOptions)
let request = MKDirectionsRequest()
request.source = MKMapItem.forCurrentLocation()
request.destination = destination
request.requestsAlternateRoutes = false
let directions = MKDirections(request: request)
// 8.
directions.calculate {
(response, error) -> Void in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
let route = response.routes[0]
self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
let rect = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
}
}
/*
directions.calculate(completionHandler: {(response: MKDirectionsResponse!, error: Error!) in
if error != nil {
print("Error \(error)")
} else {
self.displayRout(response)
var overlays = self.mapView.overlays
for route in response.routes {
self.mapView.add(route.polyline, level: MKOverlayLevel.aboveRoads)
for next in route.steps {
print(next.instructions)
}
}
}
})
}
*/
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 4.0
return renderer
}
}
//destination = MKMapItem(placemark: selectedPin!)
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController : CLLocationManagerDelegate {
// When user responds to the permission dialog
private func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.requestLocation()
}
}
// When location information comes back (Zoom to the user's current location)
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
//****
MyPosition = location.coordinate
locationManager.stopUpdatingLocation()
let span = MKCoordinateSpanMake(0.01, 0.01)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.setRegion(region, animated: true)
}
}
// Print out the error
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error finding location: \(error.localizedDescription)")
}
}
// Searches the location and city/state
extension ViewController: HandleMapSearch {
func dropPinZoomIn(placemark:MKPlacemark){
// cache the pin
selectedPin = placemark
// clear existing pins
mapView.removeAnnotations(mapView.annotations)
let annotation = MKPointAnnotation()
annotation.coordinate = placemark.coordinate
annotation.title = placemark.name
if let city = placemark.locality,
let state = placemark.administrativeArea {
annotation.subtitle = "\(city) \(state)"
}
mapView.addAnnotation(annotation)
let span = MKCoordinateSpanMake(0.01, 0.01)
let region = MKCoordinateRegionMake(placemark.coordinate, span)
mapView.setRegion(region, animated: true)
}
}
// Shows Pins and Car Logo
extension ViewController : MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.pinTintColor = UIColor.red
pinView?.canShowCallout = true
let smallSquare = CGSize(width: 30, height: 30)
let button = UIButton(frame: CGRect(origin: CGPoint.zero, size: smallSquare))
button.setBackgroundImage(UIImage(named: "Car"), for: .normal)
button.addTarget(self, action: #selector(getDirections), for: .touchUpInside)
pinView?.leftCalloutAccessoryView = button
return pinView
}
}
Have a look at below code for reference hope it helps :
1 using two locations here as source and as destination and drawing a path according to locations
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
// Do any additional setup after loading the view, typically from a nib.
let sourceLocation = CLLocationCoordinate2D(latitude: 40.759011, longitude: -73.984472)
let destinationLocation = CLLocationCoordinate2D(latitude: 40.748441, longitude: -73.985564)
// 3.
let sourcePlacemark = MKPlacemark(coordinate: sourceLocation, addressDictionary: nil)
let destinationPlacemark = MKPlacemark(coordinate: destinationLocation, addressDictionary: nil)
// 4.
let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
// 5.
let sourceAnnotation = MKPointAnnotation()
sourceAnnotation.title = "Times Square"
if let location = sourcePlacemark.location {
sourceAnnotation.coordinate = location.coordinate
}
let destinationAnnotation = MKPointAnnotation()
destinationAnnotation.title = "Empire State Building"
if let location = destinationPlacemark.location {
destinationAnnotation.coordinate = location.coordinate
}
// 6.
self.mapView.showAnnotations([sourceAnnotation,destinationAnnotation], animated: true )
// 7.
let directionRequest = MKDirectionsRequest()
directionRequest.source = sourceMapItem
directionRequest.destination = destinationMapItem
directionRequest.transportType = .walking
// Calculate the direction
let directions = MKDirections(request: directionRequest)
// 8.
directions.calculate {
(response, error) -> Void in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
let route = response.routes[0]
self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
let rect = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 4.0
return renderer
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Output :

Converting Parse PFGeoPoint into an annotation on the map

I am trying to convert a saved PFGeopoint objects in Parse server into an annotation but i can't seem to figure it out and i don't know what's wrong.
I tried to apply the code from this question : Converting Parse GeoPoint into a CLLocation in Swift but i still couldn't figure it out.
Here is my Code :
import UIKit
import MapKit
import CoreLocation
import Parse
class MapVC: UIViewController, MKMapViewDelegate {
fileprivate let locationManager = CLLocationManager()
fileprivate var startedLoadingPOIs = false
fileprivate var places = [Place]()
var descLocation: PFGeoPoint = PFGeoPoint()
var mapHasCenteredOnce = false
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
locationManager.requestWhenInUseAuthorization()
mapView.userTrackingMode = MKUserTrackingMode.followWithHeading
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView: MKAnnotationView?
if annotation.isKind(of: MKUserLocation.self) {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "User")
annotationView?.image = UIImage(named: "loc.png")
}
return annotationView
}
}
extension MapVC: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//1
if locations.count > 0 {
let location = locations.last!
print("Accuracy: \(location.horizontalAccuracy)")
//2
if location.horizontalAccuracy < 100 {
//3
manager.stopUpdatingLocation()
let span = MKCoordinateSpan(latitudeDelta: 0.014, longitudeDelta: 0.014)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.region = region
if !startedLoadingPOIs {
startedLoadingPOIs = true
let loader = PlacesLoader()
loader.loadPOIS(location: location, radius: 1000) { placesDict, error in
if let dict = placesDict {
let query = PFQuery(className: "posts")
if let latitude = (PFUser.current()?["location"] as AnyObject).latitude {
if let longitude = (PFUser.current()?["location"] as AnyObject).longitude {
let geoPoint = PFGeoPoint(latitude: latitude, longitude: longitude)
query.whereKey("postLocation", nearGeoPoint: geoPoint, withinKilometers: 1)
}
}
query.findObjectsInBackground { (objects: [PFObject]?, error: Error?) in
if error == nil {
for object in objects! {
let pfObject = object as PFObject
let caption = pfObject["title"] as! String
self.descLocation = object["postLocation"] as! PFGeoPoint
let latitude: CLLocationDegrees = self.descLocation.latitude
let longitude: CLLocationDegrees = self.descLocation.longitude
let location = CLLocation(latitude: latitude, longitude: longitude)
let place = Place(location: location, name: caption )
self.places.append(place)
let annotation = PlaceAnnotation(location: place.location!.coordinate, title: place.placeName)
DispatchQueue.main.async {
self.mapView.addAnnotation(annotation)
}
}
}
}
}
}
}
}
}
}
}
I just had two uanessacry lines that blocked the operation, removed them and it worked for me.
loader.loadPOIS(location: location, radius: 1000) { placesDict, error in
if let dict = placesDict {