Doesn't show notification after add 'self' - swift

I have project in IOS that monitor user location and when he pass near place he want , the app will notify him .. this is my code
import UIKit
import MapKit
import CoreLocation
import UserNotifications
import FirebaseDatabase
import FirebaseAuth
class testingViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var users: User?
var todoList = [Todo] ()
let usersRef = FIRDatabase.database().reference(withPath: "Users")
var snapshot: [FIRDataSnapshot]! = []
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
FIRAuth.auth()?.addStateDidChangeListener() { auth, user in
if user != nil {
guard let user = user else { return }
self.users = User(authData: user)
let currentUserRef = self.usersRef.child((self.users?.uid)!)
currentUserRef.setValue(self.users?.email)
print(user.uid)
} else {
print("Not signed in")
}
}
// 2. setup locationManager
locationManager.delegate = self;
// self.locationManager = CLLocationManager()
// locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters;
// locationManager.desiredAccuracy = kCLLocationAccuracyBest
// locationManager.startMonitoringSignificantLocationChanges()
// locationManager.startUpdatingLocation()
// setup mapView
mapView.delegate = self
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
// 4. setup test data
setupData()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// 1. status is not determined
if CLLocationManager.authorizationStatus() == .notDetermined {
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
}
// 2. authorization were denied
else if CLLocationManager.authorizationStatus() == .denied {
print("Location services were previously denied. Please enable location services for this app in Settings.")
}
// 3. we do have authorization
else if CLLocationManager.authorizationStatus() == .authorizedAlways {
// locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges();
}
}
func setupData() {
let usercur = (FIRAuth.auth()?.currentUser?.uid)!
let test = FIRDatabase.database().reference(fromURL: "https://ade-mc-trial.firebaseio.com/Data")
test.child(usercur).child("ToDoList").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
// 1. check if system can monitor regions
if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
// 2. region data
let title = "medical collage"
let coordinate = CLLocationCoordinate2DMake(25.900767, 45.3411889)
let regionRadius = 350.0
// 3. setup region
let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: coordinate.latitude,
longitude: coordinate.longitude), radius: regionRadius, identifier: title)
self.locationManager.startMonitoring(for: region)
// 4. setup annotation
let restaurantAnnotation = MKPointAnnotation()
restaurantAnnotation.coordinate = coordinate;
restaurantAnnotation.title = "\(title)";
self.mapView.addAnnotation(restaurantAnnotation)
// 5. setup circle
let circle = MKCircle(center: coordinate, radius: regionRadius)
self.mapView.add(circle)
}
else {
print("System can't track regions")
}
}})
}
// 6. draw circle
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let circleRenderer = MKCircleRenderer(overlay: overlay)
circleRenderer.strokeColor = UIColor.blue
circleRenderer.lineWidth = 1.0
return circleRenderer
}
// 1. user enter region
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
let notification = UILocalNotification()
notification.fireDate = NSDate(timeIntervalSinceNow: 0) as Date
notification.alertBody = "Hey you! Yeah you! Swipe to unlock!"
notification.alertAction = "be awesome!"
notification.soundName = UILocalNotificationDefaultSoundName
notification.userInfo = ["CustomField1": "w00t"]
UIApplication.shared.scheduleLocalNotification(notification)
/*
guard let settings = UIApplication.shared.currentUserNotificationSettings else { return }
if settings.types == .none {
let ac = UIAlertController(title: "Can't schedule", message: "Either we don't have permission to schedule notifications, or we haven't asked yet.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(ac, animated: true, completion: nil)
return
}*/
}
/* func showAlert(_ title: String) {
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
alert.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}*/
}
But when I want to link it with database - firebase- it force me to correct three lines to add " self ". I add star in lines that force me to add "self".. then the code does not work and did not display notification after add 'self'
import UIKit
import MapKit
import CoreLocation
import UserNotifications
import FirebaseDatabase
import FirebaseAuth
class testingViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var users: User?
var todoList = [Todo] ()
let usersRef = FIRDatabase.database().reference(withPath: "Users")
var snapshot: [FIRDataSnapshot]! = []
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
FIRAuth.auth()?.addStateDidChangeListener() { auth, user in
if user != nil {
guard let user = user else { return }
self.users = User(authData: user)
let currentUserRef = self.usersRef.child((self.users?.uid)!)
currentUserRef.setValue(self.users?.email)
print(user.uid)
} else {
print("Not signed in")
}
}
// 2. setup locationManager
locationManager.delegate = self;
// self.locationManager = CLLocationManager()
// locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters;
// locationManager.desiredAccuracy = kCLLocationAccuracyBest
// locationManager.startMonitoringSignificantLocationChanges()
// locationManager.startUpdatingLocation()
// setup mapView
mapView.delegate = self
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
// 4. setup test data
setupData()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// 1. status is not determined
if CLLocationManager.authorizationStatus() == .notDetermined {
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
}
// 2. authorization were denied
else if CLLocationManager.authorizationStatus() == .denied {
print("Location services were previously denied. Please enable location services for this app in Settings.")
}
// 3. we do have authorization
else if CLLocationManager.authorizationStatus() == .authorizedAlways {
// locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges();
}
}
func setupData() {
let usercur = (FIRAuth.auth()?.currentUser?.uid)!
let test = FIRDatabase.database().reference(fromURL: "https://ade-mc-trial.firebaseio.com/Data")
test.child(usercur).child("ToDoList").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
// 1. check if system can monitor regions
if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
// 2. region data
let title = "medical collage"
let coordinate = CLLocationCoordinate2DMake(25.900767, 45.3411889)
let regionRadius = 350.0
// 3. setup region
let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: coordinate.latitude,
longitude: coordinate.longitude), radius: regionRadius, identifier: title)
self.locationManager.startMonitoring(for: region)//*****************
// 4. setup annotation
let restaurantAnnotation = MKPointAnnotation()
restaurantAnnotation.coordinate = coordinate;
restaurantAnnotation.title = "\(title)";
self.mapView.addAnnotation(restaurantAnnotation)//***************
// 5. setup circle
let circle = MKCircle(center: coordinate, radius: regionRadius)
self.mapView.add(circle)//*******************************
}
else {
print("System can't track regions")
}
}})
}
// 6. draw circle
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let circleRenderer = MKCircleRenderer(overlay: overlay)
circleRenderer.strokeColor = UIColor.blue
circleRenderer.lineWidth = 1.0
return circleRenderer
}
// 1. user enter region
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
let notification = UILocalNotification()
notification.fireDate = NSDate(timeIntervalSinceNow: 0) as Date
notification.alertBody = "Hey you! Yeah you! Swipe to unlock!"
notification.alertAction = "be awesome!"
notification.soundName = UILocalNotificationDefaultSoundName
notification.userInfo = ["CustomField1": "w00t"]
UIApplication.shared.scheduleLocalNotification(notification)
}
}
Please any one have the solution?

I think the closure is not understanding the self.
In general term you should use the weak reference of self instead of the strong reference. Try by creating the weak reference of the self and putting it in the closure.
The code will be changed as below.
func setupData() {
weak var weakSelf = self //Updates
let usercur = (FIRAuth.auth()?.currentUser?.uid)!
let test = FIRDatabase.database().reference(fromURL: "https://ade-mc-trial.firebaseio.com/Data")
test.child(usercur).child("ToDoList").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
// 1. check if system can monitor regions
if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
// 2. region data
let title = "medical collage"
let coordinate = CLLocationCoordinate2DMake(25.900767, 45.3411889)
let regionRadius = 350.0
// 3. setup region
let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: coordinate.latitude,
longitude: coordinate.longitude), radius: regionRadius, identifier: title)
weakSelf.locationManager.startMonitoring(for: region)//Updates
// 4. setup annotation
let restaurantAnnotation = MKPointAnnotation()
restaurantAnnotation.coordinate = coordinate;
restaurantAnnotation.title = "\(title)";
weakSelf.mapView.addAnnotation(restaurantAnnotation)//Updates
// 5. setup circle
let circle = MKCircle(center: coordinate, radius: regionRadius)
weakSelf.mapView.add(circle)//Updates
}
else {
print("System can't track regions")
}
}})
}

Related

How to replace new location coordinates in current location coordinates in MKMapView in swift

I am using map in Two viewcontrollers
Initially in first viewcontroller i am getting current location in map..
in second viewcontroller i am getting new location coordinates, which i am sending to firstview controller using delegate.. but here how to replace the delegate method coordinates with current location coordinates in first view controller
first view controller code: here in delegate method i am successfully having new location coordinates which i need replace with current location
in userDidEnterInformationdelegate method i am getting all values from 2nd view controller
import UIKit
import CoreLocation
import MapKit
class ProfileAddressViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate, DataEnteredDelegate {
var coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D()
let locationManager = CLLocationManager()
var latitude: Double?
var logitude: Double?
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.requestAlwaysAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
}
}
func userDidEnterInformation(info: DataEnteredModelSave) {
print("map address viewcontroller data \(info)")
self.pincodeField.text = info.pinCode
self.cityField.text = info.cityField
self.latitude = info.zLatitude
self.self.logitude = info.zLongitude
print("new map address viewcontroller data info lat long \(self.latitude) \(self.logitude)")
}
#IBAction func submitButtonClicked(_ sender: UIButton) {
self.view.endEditing(true)
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "NewZoomAddressViewController") as! NewZoomAddressViewController;
self.navigationController?.pushViewController(viewController, animated: true);
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let _: CLLocationCoordinate2D = manager.location?.coordinate else { return }
let userLocation :CLLocation = locations.last! as CLLocation
latitude = userLocation.coordinate.latitude
logitude = userLocation.coordinate.longitude
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(userLocation) { (placemarks, error) in
if (error != nil){
print("error in reverseGeocode")
}
let placemark = placemarks! as [CLPlacemark]
if placemark.count>0{
let placemark = placemarks![0]
let placemarkDictonary: NSDictionary=placemark.addressDictionary as! NSDictionary
self.pincodeField.text=placemarkDictonary["ZIP"] as? String
self.cityField.text=placemarkDictonary["City"] as? String
}
}
let center = CLLocationCoordinate2D(latitude: latitude!, longitude: logitude!)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
mapView.setRegion(region, animated: true)
let myAnnotation: MKPointAnnotation = MKPointAnnotation()
myAnnotation.coordinate = CLLocationCoordinate2DMake(userLocation.coordinate.latitude, userLocation.coordinate.longitude);
myAnnotation.title = "Current location"
mapView.addAnnotation(myAnnotation)
}
}
please help me to add delegate method latitude and longitude in locationManager didUpdateLocations
Replace userDidEnterInformation with below code:
func userDidEnterInformation(info: DataEnteredModelSave) {
print("map address viewcontroller data \(info)")
self.pincodeField.text = info.pinCode
self.streetField.text = info.streetField
self.cityField.text = info.cityField
self.latitude = info.zLatitude
self.logitude = info.zLongitude
print("map address viewcontroller data info lat long \(self.latitude) \(self.logitude)")
locationManager.stopUpdatingLocation() //stop updating location when you got data from delegate
let userLocation = CLLocation.init(latitude: latitude!, longitude: logitude!)
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(userLocation) { (placemarks, error) in
if (error != nil){
print("error in reverseGeocode")
}
let placemark = placemarks! as [CLPlacemark]
if placemark.count>0{
let placemark = placemarks![0]
print(placemark.locality!)
print(placemark.administrativeArea!)
print(placemark.country!)
let placemarkDictonary: NSDictionary=placemark.addressDictionary as! NSDictionary
self.pincodeField.text=placemarkDictonary["ZIP"] as? String
self.cityField.text=placemarkDictonary["City"] as? String
self.plotField.text=placemarkDictonary["Name"] as? String
self.streetField.text=placemarkDictonary["Street"] as? String
self.appormentNoField.text=placemarkDictonary["SubThoroughfare"] as? String
self.colonyField.text=placemarkDictonary["SubLocality"] as? String
self.landmarkField.text=placemarkDictonary["SubThoroughfare"] as? String
}
}
let center = CLLocationCoordinate2D(latitude: latitude!, longitude: logitude!)
//Assign data to map again with new location
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
mapView.setRegion(region, animated: true)
let myAnnotation: MKPointAnnotation = MKPointAnnotation()
myAnnotation.coordinate = CLLocationCoordinate2DMake(latitude!, logitude!)
myAnnotation.title = "Current location"
mapView.addAnnotation(myAnnotation)
}
I have added comments please check them.
EDIT: As per your second request if you want to show new coordinates on NewZoomAddressViewController first you need to pass coordinates to NewZoomAddressViewController in submitButtonClicked method like:
viewController.latestLocation = CLLocation.init(latitude: self.latitude!, longitude: self.logitude!)
then in NewZoomAddressViewController declare new var
var latestLocation: CLLocation?
and remove other code which is related to user's current location and final code will look like:
import UIKit
import MapKit
import CoreLocation
//import SwiftKeychainWrapper
protocol DataEnteredDelegate: class {
func userDidEnterInformation(info: DataEnteredModelSave)
}
class NewZoomAddressViewController: UIViewController {
#IBOutlet weak var oneBtnContainerView: UIView!
var latitudeZoom: Double?
var logitudeZoom: Double?
weak var delegate: DataEnteredDelegate? = nil
var zipName: String?
var localityName: String?
var sublocalityName: String?
var streetNumber: String?
var streetName: String?
let searchCont = UISearchController(searchResultsController: nil)
let annotation = MKPointAnnotation()
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var addressLabel: UILabel!
let regionInMeters: Double = 10000
var previousLocation: CLLocation?
var latestLocation: CLLocation?
override func viewDidLoad() {
super.viewDidLoad()
print("in Zoom map VC")
mapView.delegate = self
addressLabel.text = "\(self.sublocalityName!) \(localityName!) \(self.zipName!)"
centerViewOnUserLocation()
}
#IBAction func backBtn(_ sender: Any) {
self.navigationController?.popViewController(animated: true)
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isHidden=true
}
var viewController: UIViewController?
#IBAction func confirmBtn(_ sender: Any) {
guard
let zipName = zipName,
let sublocalityName = sublocalityName,
let localityName = localityName,
let lnatZ = latitudeZoom,
let longZ = logitudeZoom
else { return }
let enteredData = DataEnteredModelSave(pinCode: zipName, streetField: sublocalityName, cityField: localityName, zLatitude: lnatZ, zLongitude: longZ)
delegate?.userDidEnterInformation(info: enteredData)
self.navigationController?.popViewController(animated: true)
}
func centerViewOnUserLocation() {
if let location = latestLocation {
let region = MKCoordinateRegion.init(center: location.coordinate, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
mapView.setRegion(region, animated: true)
}
}
func getCenterLocation(for mapView: MKMapView) -> CLLocation {
latitudeZoom = mapView.centerCoordinate.latitude
logitudeZoom = mapView.centerCoordinate.longitude
print("coordinates from zoom in func \(latitudeZoom), \(logitudeZoom)")
return CLLocation(latitude: latitudeZoom!, longitude: logitudeZoom!)
//print(CLLocation.self)
}
}
extension NewZoomAddressViewController: CLLocationManagerDelegate, UISearchBarDelegate {
// MARK:- Search Address
#IBAction func searchLocationButton(_ sender: Any) {
// let searchCont = UISearchController(searchResultsController: nil)
searchCont.searchBar.delegate = self
searchCont.searchBar.backgroundColor = .blue
present(searchCont, animated:true, completion:nil)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
dismiss(animated: true, completion: nil)
//create the search request
let searchReq = MKLocalSearch.Request()
searchReq.naturalLanguageQuery = searchBar.text
let activeSearch = MKLocalSearch(request: searchReq)
activeSearch.start { (response, error) in
UIApplication.shared.endIgnoringInteractionEvents()
if response == nil{
print("error")
}
else{
//remove annotation
//let annotations = self.mapView.annotations
// self.mapView.removeAnnotation(annotations as! MKAnnotation)
//getting data
let lat = response?.boundingRegion.center.latitude
let long = response?.boundingRegion.center.longitude
//create annotation
//let annotation = MKPointAnnotation()
self.annotation.title = searchBar.text
self.annotation.coordinate = CLLocationCoordinate2DMake(lat!, long!)
self.mapView.addAnnotation(self.annotation)
//zooming annotation
let coordinate: CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat!, long!)
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
let region = MKCoordinateRegion(center: coordinate, span: span)
self.mapView.setRegion(region, animated: true)
// Add below code to get search address
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: lat!, longitude: long!)
geoCoder.reverseGeocodeLocation(location, completionHandler:
{
placemarks, error -> Void in
// Place details
guard let placeMark = placemarks?.first else { return }
// Location name
self.zipName = placeMark.postalCode
self.localityName = placeMark.locality
self.sublocalityName = placeMark.subLocality
self.streetNumber = placeMark.subThoroughfare
self.streetName = placeMark.thoroughfare
})
}
}
}
}
extension NewZoomAddressViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
let center = getCenterLocation(for: mapView)
let geoCoder = CLGeocoder()
guard let previousLocation = self.latestLocation else { return }
guard center.distance(from: previousLocation) > 50 else { return }
self.previousLocation = center
let userLocation :CLLocation = center as CLLocation
latitudeZoom = userLocation.coordinate.latitude
logitudeZoom = userLocation.coordinate.longitude
print("snajxhdwuidhwiuqhdxiqwjmdio \(latitudeZoom), \(logitudeZoom)")
geoCoder.reverseGeocodeLocation(center) { [weak self] (placemarks, error) in
guard let self = self else { return }
if let _ = error {
//TODO: Show alert informing the user
return
}
guard let placemark = placemarks?.first else {
//TODO: Show alert informing the user
return
}
self.streetNumber = placemark.subThoroughfare ?? ""
self.streetName = placemark.thoroughfare ?? ""
print("street number of zoom map \(self.streetName)")
self.localityName = placemark.locality ?? ""//locality
self.sublocalityName = placemark.subLocality ?? ""//locality
self.zipName = placemark.postalCode ?? ""//locality
DispatchQueue.main.async {
self.addressLabel.text = "\(self.streetNumber ?? "") \(self.streetName ?? "") \(self.sublocalityName ?? "") \(self.zipName ?? "") \(self.localityName ?? "")"
print("zzooom map location label \(self.addressLabel.text)")
}
}
}
}

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;
}
}

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 :

Getting user's location not working after Swift 4 update

I've just updated to the Xcode 9 and Swift 4 and it has broken at lot of my functions. One of which being how I get the user's location, zoom in on it on launch, detecting annotation selection and various other tasks. They don't work at all. My view controller class code is below.
import UIKit
import MapKit
import Firebase
import FirebaseDatabase
import Pulley
import CoreLocation
class ChildMapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
let manager = CLLocationManager()
var isInitialized = false
func startBackgroundLocationUpdates() {
self.manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
manager.pausesLocationUpdatesAutomatically = true
manager.activityType = .fitness
manager.allowsBackgroundLocationUpdates = true
manager.startMonitoringSignificantLocationChanges()
manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
if !isInitialized {
isInitialized = true
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
mapView.setRegion(region, animated: true)
self.mapView.showsUserLocation = true
}
}
struct loc {
let title: String
let latitude: Double
let longitude: Double
}
var locs = [
loc(title: "New York, NY", latitude: 40.713054, longitude: -74.007228),
]
func placeAnnotations() {
let annotations = locs.map { location -> MKAnnotation in
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
annotation.title = location.title
return annotation
}
mapView.addAnnotations(annotations)
}
var position:PulleyPosition!
func mapView(_ didSelectmapView: MKMapView, didSelect view: MKAnnotationView) {
Shared.shared.annotation = view.annotation!
if Shared.shared.annotation is MKUserLocation {
Shared.shared.nameString = "My Location"
} else {
loadData()
}
}
func mapView(_ mapView: MKMapView, didDeselect view:
MKAnnotationView) {
let drawerContent = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DrawerViewController")
if let drawer = self.parent?.parent as? PulleyViewController {
drawer.setDrawerContentViewController(controller: drawerContent, animated: false)
drawer.setDrawerPosition(position: PulleyPosition.partiallyRevealed, animated: true)
}
}
func loadData() {
let number = (Shared.shared.annotation?.title)!
if let number = number {
let ref = FIRDatabase.database().reference()
ref.child("safehouses").child("\(number)").observeSingleEvent(of: .value, with: { snapshot in
let snapDict = snapshot.value as? NSDictionary
let name = snapDict?["name"] as? String
let phone = snapDict?["phone"] as? String
let current = CLLocation(latitude: (self.manager.location?.coordinate.latitude)!, longitude: (self.manager.location?.coordinate.longitude)!)
let destination = CLLocation(latitude: Shared.shared.annotation.coordinate.latitude, longitude: Shared.shared.annotation.coordinate.longitude)
let distance2 = current.distance(from: destination)
let distance1 = round(distance2)
if distance1 >= 1000 {
if distance1 < 10000 {
let distance3 = distance1/1000
let distance = Double(round(10*distance3)/10)
Shared.shared.typeString = "Safehouse · " + String(distance) + " km"
} else {
let distance3 = distance1/1000
let distance = round(distance3)
Shared.shared.typeString = "Safehouse · " + String(distance) + " km"
}
} else {
let distance = self.forTailingZero(temp: distance1)
Shared.shared.typeString = "Safehouse · " + distance + " m"
}
if let name = name {
if let phone = phone {
Shared.shared.nameString = name
Shared.shared.phoneString = phone
let drawerContent = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NewDrawerViewController")
if let drawer = self.parent?.parent as? PulleyViewController {
drawer.setDrawerContentViewController(controller: drawerContent, animated: false)
drawer.setDrawerPosition(position: PulleyPosition.partiallyRevealed, animated: true)
}
}
}
})
}
}
func forTailingZero(temp: Double) -> String{
var tempVar = String(format: "%g", temp)
return tempVar
}
func loop() {
let ref = FIRDatabase.database().reference()
ref.child("safehouses").observeSingleEvent(of: .value, with: { snapshot in
let snapDict = snapshot.value as? NSDictionary
let ii = snapDict?["number"] as? Int
let iii = Int(ii!)
var i = 1
while i <= iii{
let name = String(i)
ref.child("safehouses").child("\(i)").observeSingleEvent(of: .value, with: { snapshot in
let snapDict = snapshot.value as? NSDictionary
let longitude = snapDict?["longitude"]
as? String
let latitude = snapDict?["latitude"] as? String
if let longitude = longitude {
if let latitude = latitude {
let latitude1 = Double(latitude)
if let latitude1 = latitude1 {
let longitude1 = Double(longitude)
if let longitude1 = longitude1 {
self.locs.append(loc(title: name, latitude: latitude1, longitude: longitude1))
self.placeAnnotations()
}
}
}
}
})
i = i + 1
}
})
}
#IBOutlet weak var menuButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
self.revealViewController().rearViewRevealWidth = 175
self.revealViewController().toggleAnimationType = SWRevealToggleAnimationType.easeOut
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
loop()
mapView.delegate = self
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestAlwaysAuthorization()
Shared.shared.mapView = self.mapView
startBackgroundLocationUpdates()
}
}
final class Shared {
static let shared = Shared()
var nameString : String!
var phoneString : String!
var annotation : MKAnnotation!
var mapView : MKMapView!
var typeString : String!
}
First add these property in info.plist
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>description1</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>description2</string>
<key>NSLocationUsageDescription</key>
<string>description3</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>accept to get location</string>
<key>UIBackgroundModes</key>
And then after copy this view controller in your project
import UIKit
import CoreLocation
class ViewController: UIViewController,CLLocationManagerDelegate {
var locationManager:CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
determineMyCurrentLocation()
// Do any additional setup after loading the view.
}
func determineMyCurrentLocation() {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager!.allowsBackgroundLocationUpdates = true
locationManager!.pausesLocationUpdatesAutomatically = false
let value = locationManager.startMonitoringSignificantLocationChanges()
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didStartMonitoringFor region: CLRegion) {
print("ankur :- \(region)")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
print("user latitude = \(userLocation.coordinate.latitude)")
print("user longitude = \(userLocation.coordinate.longitude)")
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
{
print("Error \(error)")
}
}
Last step :- Open Capabilities -> In background modes -> click on location updates
If any query comment it
You need to add these keys in info plist :
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>

Map not reading code first time in Swift2 iOS9

I'm trying to display some shops in my map and it's working fine (the second time the user go to that MapViewController, but the first time (when it's asking for the user permission location) it only displays the user location and the map is not "zoomed" in the user location.
I'm going to show my code, it's very straightforward and simple:
Updated with the new code (it's still not working and the "didChangeAuthorizationStatus" is not printing anything:
import UIKit
import MapKit
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
let LoadURL = "http://www.website.es/shops.json"
var coordinates = CLLocation()
#IBOutlet weak var mapView:MKMapView!
var farmacia = [Farmacia]()
let locationManager = CLLocationManager()
var currentLocation = CLLocation()
var latitudeValor = String()
var longitudeValor = String()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
// Request for a user's authorization for location services
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation()
requestLocation()
}
}
func requestLocation () {
let status = CLLocationManager.authorizationStatus()
if status == CLAuthorizationStatus.AuthorizedWhenInUse || status == CLAuthorizationStatus.AuthorizedAlways {
self.mapView.showsUserLocation = true
var currentLocation = CLLocation()
print(locationManager.location)
if locationManager.location != nil
{
currentLocation = locationManager.location!
let center = CLLocationCoordinate2D(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
latitudeValor = String(currentLocation.coordinate.latitude)
longitudeValor = String(currentLocation.coordinate.longitude)
self.mapView.setRegion(region, animated: true)
requestPost()
mapView.delegate = self
}
}
}
func locationManager(locationManager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .NotDetermined:
self.locationManager.requestWhenInUseAuthorization()
break
case .AuthorizedWhenInUse:
self.locationManager.startUpdatingLocation()
requestLocation()
break
case .AuthorizedAlways:
self.locationManager.startUpdatingLocation()
requestLocation()
break
case .Restricted:
// restricted by e.g. parental controls. User can't enable Location Services
break
case .Denied:
// user denied your app access to Location Services, but can grant access from Settings.app
break
}
}
/*
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
let location = locations.last as! CLLocation
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
requestPost()
mapView.delegate = self
}
*/
func requestPost () {
let myUrl = NSURL(string: "http://www.website.es/shops_by_position.php");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST"
let postString = "latitude="+latitudeValor+"&longitude="+longitudeValor
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
// JSON RESULTADO ENTERO
//let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
//print("responseString = \(responseString)")
if error != nil
{
//print("error=\(error)")
return
}
else
{
self.farmacia = self.parseJsonData(data!)
}
}
task.resume()
}
func parseJsonData(data: NSData) -> [Farmacia] {
let farmacias = [Farmacia]()
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
// Parse JSON data
let jsonProductos = jsonResult?["farmacias"] as! [AnyObject]
//print(jsonProductos)
for jsonProducto in jsonProductos {
let farmacia = Farmacia()
farmacia.id = jsonProducto["id"] as! String
farmacia.nombre = jsonProducto["nombre"] as! String
farmacia.latitude = jsonProducto["latitude"] as! String
farmacia.longitude = jsonProducto["longitude"] as! String
let stringLat = NSString(string: farmacia.latitude)
let stringLon = NSString(string: farmacia.longitude)
let latitude: CLLocationDegrees = stringLat.doubleValue
let longitude: CLLocationDegrees = stringLon.doubleValue
coordinates = CLLocation(latitude: latitude,longitude: longitude)
let geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(coordinates, completionHandler: { placemarks, error in
if error != nil
{
//print(error)
return
}
else
{
if placemarks != nil && placemarks!.count > 0 {
let placemark = placemarks?[0]
// Add Annotation
let annotation = MKPointAnnotation()
annotation.title = farmacia.nombre
annotation.coordinate = placemark!.location!.coordinate
self.mapView.addAnnotation(annotation)
}
}
})
}
}
catch let parseError {
print(parseError)
}
return farmacias
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "MyPin"
if annotation.isKindOfClass(MKUserLocation) {
return nil
}
let detailButton: UIButton = UIButton(type: UIButtonType.DetailDisclosure)
// Reuse the annotation if possible
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if annotationView == nil
{
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "pin")
annotationView!.canShowCallout = true
annotationView!.image = UIImage(named: "pin.png")
annotationView!.rightCalloutAccessoryView = detailButton
}
else
{
annotationView!.annotation = annotation
}
return annotationView
}
func mapView(mapView: MKMapView, annotationView: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == annotationView.rightCalloutAccessoryView {
performSegueWithIdentifier("PinDetail2", sender: annotationView)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "PinDetail" {
let destinationController = segue.destinationViewController as! FarmaciaDetailViewController
destinationController.titulo_farmacia = (sender as! MKAnnotationView).annotation!.title!
}
if segue.identifier == "PinDetail2" {
let destinationController = segue.destinationViewController as! FarmaciaWebDetailViewController
destinationController.nombre_farmacia = (sender as! MKAnnotationView).annotation!.title!
}
}
#IBAction func cancelToMap(segue:UIStoryboardSegue) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
My question is: What I have to change in order to show the user location zoomed and my shop entries the first time the app asks for permission and the user choose "Yes"?
It's my first time using the MapKit framework and I'm a little bit lost, so much appreciated if you can show me some light in my case.
1) Change
class MapViewController: UIViewController, MKMapViewDelegate {
to
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
2) Change
func locationManager(locationManager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .NotDetermined:
self.locationManager.requestAlwaysAuthorization()
to
self.locationManager.requestWhenInUseAuthorization()
3) Add NSLocationWhenInUseUsageDescription to Info.plist
EDIT
4) Add the following code to viewDidLoad
locationManager.delegate = self
EDIT 2
5) Add import to header
import CoreLocation
The documentation for requestWhenInUseAuthorization says
When the current authorization status is kCLAuthorizationStatusNotDetermined, this method runs asynchronously and prompts the user to grant permission to the app to use location services.
So in your code, the authorisation is requested and then execution immediately continues, eventually reaching
if status == CLAuthorizationStatus.AuthorizedWhenInUse
which fails, at status is still not determined.
There is the locationManager:didChangeAuthorizationStatus: callback in CLLocationManagerDelegate that is called once the user allows or denies location access.
I would suggest that you move your logic for the .AuthorizedWhenInUse case in a function and call it either from your viewDidLoad method for cases when authorisation is already granted or from the callback if it is not granted yet.