On a xcode application, I display many pins from my database and my position but the map is not centered on my position
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Create coordinates from location lat/long
var poiCoodinates = CLLocationCoordinate2D()
tab = selectedEtablissement as! [EtablissementModel]
for item in 0..<tab.count{
poiCoodinates.latitude = tab[item].lonetablissement!
poiCoodinates.longitude = tab[item].lngetablissement!
// Zoom to region
let viewRegion: MKCoordinateRegion = MKCoordinateRegion.init(center: poiCoodinates, latitudinalMeters: 750, longitudinalMeters: 750)
self.mapB******.setRegion(viewRegion, animated: true)
// Plot pin
let pin: MKPointAnnotation = MKPointAnnotation()
pin.coordinate = poiCoodinates
self.mapB*******.addAnnotation(pin)
//add title to the pin
pin.title = tab[item].nometablissement
}
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.startUpdatingLocation()
mapBieres.showsUserLocation = true
self.locationManager.stopUpdatingLocation()
}
The pins are displayed on many cities and with this code, my position is displayed but the map is not centered on my position. I want all the pins on the map but the map centered on my position. Thanks
`import MapKit
import CoreLocation
class ViewController: UIViewController {
var locationManager = CLLocationManager()
#IBOutlet weak var mapView: MKMapView!
func setLocation() { // Seeting up current location
locationManager.delegate = self as CLLocationManagerDelegate
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
// Setting the current location to the ashton building, & the zoom of the map
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locationOfUser = locations[0]
let lat = locationOfUser.coordinate.latitude
let long = locationOfUser.coordinate.longitude
let latDelta: CLLocationDegrees = 0.003 // Distance from the map
let lonDelta: CLLocationDegrees = 0.003
let span = MKCoordinateSpan(latitudeDelta: latDelta, longitudeDelta: lonDelta)
let location = CLLocationCoordinate2D(latitude: lat, longitude: long)
let region = MKCoordinateRegion(center: location, span: span)
mapView.setRegion(region, animated: true)
}
}`
The following code should help you set up your current location, as well as the distance zoom of the map. (make sure current location is turned on in settings, if I remember correctly).
Hope this can help in anyway, had to look through my old Swift assignments:)
Related
i want to make MKPointAnnotation fixed to centre of the map even while scrolling, i try to make it but MKPointAnnotation is not move while scrolling
here is my code :
import UIKit
import MapKit
class HomeVC: UIViewController,MKMapViewDelegate,CLLocationManagerDelegate {
#IBOutlet var myMap: MKMapView!
private var locationManager = CLLocationManager();
private var userLocation: CLLocationCoordinate2D?;
// private var riderLocation: CLLocationCoordinate2D
override func viewDidLoad() {
super.viewDidLoad()
initializeLocationManager()}
// find location on the map
private func initializeLocationManager(){
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// if we hade the coordinate from the manager
if let location = locationManager.location?.coordinate {
userLocation = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
// the place the map will show (ZOOM LVL ON MAP)
let region = MKCoordinateRegion(center: userLocation!, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
myMap.setRegion(region, animated: true)
//To Remove annotation = Point on map befor add new one
myMap.removeAnnotations(myMap.annotations)
//Show My Point At Map
let annotation = MKPointAnnotation();
annotation.coordinate = myMap.centerCoordinate
myMap.addAnnotation(annotation)
}
}
}
Try the following code:
// Show My Point At Map
let annotation = MKPointAnnotation()
annotation.coordinate = myMap.region.center // instead of myMap.centerCoordinate
myMap.addAnnotation(annotation)
EDIT:
You need to call stopUpdatingLocation() in didUpdateLocations method.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// if we hade the coordinate from the manager
if let location = locationManager.location?.coordinate {
userLocation = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
// the place the map will show (ZOOM LVL ON MAP)
let region = MKCoordinateRegion(center: userLocation!, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
myMap.setRegion(region, animated: true)
locationManager.stopUpdatingLocation() // <- Stop updating
}
}
And you should use regionDidChangeAnimated method to make MKPointAnnotation fixed to centre of the map even while scrolling,
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
// To Remove annotation = Point on map befor add new one
myMap.removeAnnotations(myMap.annotations)
let annotation = MKPointAnnotation();
annotation.coordinate = myMap.region.center
myMap.addAnnotation(annotation)
}
I'm making an app to search the location. It contains a VC(viewcontroller) to show the searching record.
Q1. How to get the input in textfield and show the location in the mapview?
Q2. I can't unwind the viewcontroller. I've done the code and wire in the storyboard. But still do nothing.
Q3. How to pass the data in the textfield in VC A to the tableview in VC B when a button is clicked?
Or am I do it wrong?
The code:
#IBAction func unwind(segue: UIStoryboardSegue) {
viewController?.dismiss(animated: true)
self.performSegue(withIdentifier: "unwindToMap", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
//Check for Location Services
if (CLLocationManager.locationServicesEnabled()) {
myLocationManager = CLLocationManager()
myLocationManager.delegate = mapViewDelegate as? CLLocationManagerDelegate
myLocationManager.desiredAccuracy = kCLLocationAccuracyBest
myLocationManager.requestAlwaysAuthorization()
myLocationManager.requestWhenInUseAuthorization()
}
mapViewDelegate = searchBox.text as? MKMapViewDelegate
}
#IBAction func searchButtonClick(_ sender: Any) {
let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let span = MKCoordinateSpanMake(0.005, 0.005)
let region = MKCoordinateRegion(center: location, span: span)
let annotation = MKPointAnnotation()
annotation.coordinate = location
annotation.title = searchBox.text!
/*
//find the words
let _ : UITextPosition = searchBox.beginningOfDocument
let _ : UITextPosition = searchBox.endOfDocument
let _ : UITextRange = searchBox.selectedTextRange!
// Get cursor position
if let selectedRange = searchBox.selectedTextRange {
_ = searchBox.offset(from: searchBox.beginningOfDocument, to: selectedRange.start)
}
searchBox.selectedTextRange = searchBox.textRange(
from: searchBox.beginningOfDocument, to: searchBox.endOfDocument)
*/
// myMapView.add(location as! MKOverlay)
myMapView.addAnnotation(annotation)
myMapView.setRegion(region, animated: true)
}
If your answer is useful, I'll be very appreciated.
Edit:
(24 July 2019)Any more better answers? Although I've reproduce the problem.
It's welcomed that more answers for your reference.
For current location you can use the below code:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
let center = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
mapView.setRegion(region, animated: true)
// Drop a pin at user's Current Location
let myAnnotation: MKPointAnnotation = MKPointAnnotation()
myAnnotation.coordinate = CLLocationCoordinate2DMake(userLocation.coordinate.latitude, userLocation.coordinate.longitude);
myAnnotation.title = "Current location"
mapView.addAnnotation(myAnnotation)
}
To pass Data from one screen to another you can make use of Structs
Like:
struct Manager
{
static var tfText : String = ""
}
To Update its content From anywhere use
Manager.tfText = textField.text!
To retrive data Same as Above
let variable : String = Manager.tfText
you can make use of navigation controller to pop controller, if need to use unwind did you connected your source vc to unwind segue in storyboard
Currently, my code drops a pin on the user's current location. There is one small problem when I try to move the map around, because the view will shift back and be centered around that current location pin. I want the user be able to navigate the map and move it around, and if the user switches view controllers (goes to another tab) and comes back, the map will be centered around the user location pin. I have been trying to modify this code to do this, but I have not had any luck where to start.
import UIKit
import MapKit
import CoreLocation
let newPin = MKPointAnnotation()
class MapVC: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// User's location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
if #available(iOS 8.0, *) {
locationManager.requestAlwaysAuthorization()
} else {
// Fallback on earlier versions
}
locationManager.startUpdatingLocation()
// add gesture recognizer
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(MapVC.mapLongPress(_:))) // colon needs to pass through info
longPress.minimumPressDuration = 1.5 // in seconds
//add gesture recognition
map.addGestureRecognizer(longPress)
}
// func called when gesture recognizer detects a long press
func mapLongPress(_ recognizer: UIGestureRecognizer) {
print("A long press has been detected.")
let touchedAt = recognizer.location(in: self.map) // adds the location on the view it was pressed
let touchedAtCoordinate : CLLocationCoordinate2D = map.convert(touchedAt, toCoordinateFrom: self.map) // will get coordinates
let newPin = MKPointAnnotation()
newPin.coordinate = touchedAtCoordinate
map.addAnnotation(newPin)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
map.removeAnnotation(newPin)
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))
//set region on the map
map.setRegion(region, animated: true)
newPin.coordinate = location.coordinate
map.addAnnotation(newPin)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Your code has several problems:
You declare a variable newPin at global scope and in mapLongPress(...) you declare a new variable let newPin = ... locally so the global newPin isn't used.
In didUpdateLocations() you first remove the (global) newPin annotation (why??) and set it again at the end of the function. Because the global newPin was never set to anything useful this will never get the desired result.
Furthermore, in didUpdateLocations() you set the map's region and center point to the current location. This is done on every location update, giving weird results when trying to pan the map.
To set center and region when the view appears, try something like that:
class MapVC: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
// class variable for the current location
var lastLocation: CLLocation?
override func viewDidLoad() {
// ...
}
override func viewDidAppear(_ animated: Bool) {
if self.lastLocation != nil {
// set center and region to current location
let center = CLLocationCoordinate2D(latitude: self.lastLocation.coordinate.latitude, longitude: self.lastLocation.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
//set region on the map
map.setRegion(region, animated: true)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
self.lastLocation = locations.last
}
}
Currently, my code drops a pin on the user's current location. There is one small problem when I try to move the map around, because the view will shift back and be centered around that current location pin. I want the user be able to navigate the map and move it around, and if the user switches view controllers (goes to another tab) and comes back, the map will be centered around the user location pin. I have been trying to modify this code to do this, but I have not had any luck where to start.
import UIKit
import MapKit
import CoreLocation
let newPin = MKPointAnnotation()
class MapVC: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// User's location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
if #available(iOS 8.0, *) {
locationManager.requestAlwaysAuthorization()
} else {
// Fallback on earlier versions
}
locationManager.startUpdatingLocation()
// add gesture recognizer
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(MapVC.mapLongPress(_:))) // colon needs to pass through info
longPress.minimumPressDuration = 1.5 // in seconds
//add gesture recognition
map.addGestureRecognizer(longPress)
}
// func called when gesture recognizer detects a long press
func mapLongPress(_ recognizer: UIGestureRecognizer) {
print("A long press has been detected.")
let touchedAt = recognizer.location(in: self.map) // adds the location on the view it was pressed
let touchedAtCoordinate : CLLocationCoordinate2D = map.convert(touchedAt, toCoordinateFrom: self.map) // will get coordinates
let newPin = MKPointAnnotation()
newPin.coordinate = touchedAtCoordinate
map.addAnnotation(newPin)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
map.removeAnnotation(newPin)
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))
//set region on the map
map.setRegion(region, animated: true)
newPin.coordinate = location.coordinate
map.addAnnotation(newPin)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You can use custom location manager class and call the singleton function in didfinishlaunching with option and save latitude and longitude in UserDefault .Set camera position in viewDidLoad for mapView class
1.Make singleton class
var locationShareInstance:locationManagerClass = locationManagerClass()
class locationManagerClass: NSObject, CLLocationManagerDelegate, WebServiceDelegate , UIAlertViewDelegate
{
var locationManager = CLLocationManager()
class func sharedLocationManager() -> locationManagerClass
{
locationShareInstance = locationManagerClass()
return locationShareInstance
}
func startStandardUpdates() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.activityType = .automotiveNavigation
locationManager.distanceFilter = 10
locationManager.pausesLocationUpdatesAutomatically = false
if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) {
locationManager.requestWhenInUseAuthorization()
}
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// If it's a relatively recent event, turn off updates to save power.
let location: CLLocation = locations.last!
let strLocation = "\(location.coordinate.latitude)"
if strLocation == "" {
}else{
UserDefaults.standard.set("\(location.coordinate.latitude)", forKey: "lat")
UserDefaults.standard.set("\(location.coordinate.longitude)", forKey: "long")
UserDefaults.standard.synchronize()
debugPrint("Spedd: \(location.speed)")
// self.updateLocationToServer()
self.stopStandardUpdate()
}
}
func stopStandardUpdate(){
locationManager.stopUpdatingLocation()
}
//MARK:- WHEN DENIED
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.denied {
NSLog("DENIAL")
UserDefaults.standard.set("\(0.0)", forKey: "lat")
UserDefaults.standard.set("\(0.0)", forKey: "long")
self.generateAlertToNotifyUser()
}
}
func generateAlertToNotifyUser() {
if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.notDetermined{
var title: String
title = ""
let message: String = "Location Services are not able to determine your location"
let alertView: UIAlertView = UIAlertView(title: title, message: message, delegate: self, cancelButtonTitle: "Cancel", otherButtonTitles: "Settings")
alertView.show()
}
if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.denied{
var title: String
title = "Location services are off"
let message: String = "To post spots or find near by spots, you must turn on Location Services from Settings"
let alertView: UIAlertView = UIAlertView(title: title, message: message, delegate: self, cancelButtonTitle: "Cancel", otherButtonTitles: "Settings")
alertView.show()
}
if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.notDetermined
{
startStandardUpdates()
}
}
}
Call this functions in didfinishlaunchingwithoption
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let locationManager = locationManagerClass.sharedLocationManager()
locationManager.startStandardUpdates()
}
3.Set camera in viewDidLoad of your class
if UserDefaults.standard.object(forKey: "lat") != nil {
let lat = UserDefaults.standard.object(forKey: "lat") as! String
let long = UserDefaults.standard.object(forKey: "long") as! String
var userLoc = CLLocationCoordinate2D()
userLoc.latitude = CDouble(lat)!
userLoc.longitude = CDouble(long)!
let span = MKCoordinateSpanMake(0.02, 0.02)
let region = MKCoordinateRegion(center: userLoc, span: span)
mapVw.setRegion(region, animated: true)
mapVw.showsUserLocation = true
}
I want to be able to send my current location to another iPhone user. I can get my current location and continuously update my location to see where I am on the map but how could I send this info to another iPhone user so they can see where i am in real time?
The basic structure of code is:
import UIKit
import MapKit
class ViewController: UIViewController,CLLocationManagerDelegate {
#IBOutlet weak var myMapView: MKMapView!
let myLocMgr = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
myLocMgr.desiredAccuracy = kCLLocationAccuracyBest
myLocMgr.requestWhenInUseAuthorization()
myLocMgr.startUpdatingLocation()
myLocMgr.delegate = self
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// get most recient coordinate
let myCoor = locations[locations.count - 1]
//get lat & long
let myLat = myCoor.coordinate.latitude
let myLong = myCoor.coordinate.longitude
let myCoor2D = CLLocationCoordinate2D(latitude: myLat, longitude: myLong)
//set span
let myLatDelta = 0.05
let myLongDelta = 0.05
let mySpan = MKCoordinateSpan(latitudeDelta: myLatDelta, longitudeDelta: myLongDelta)
let myRegion = MKCoordinateRegion(center: myCoor2D, span: mySpan)
//center map at this region
myMapView.setRegion(myRegion, animated: true)
//add anotation
let myAnno = MKPointAnnotation()
myAnno.coordinate = myCoor2D
myMapView.addAnnotation(myAnno)
}