How to send current location to another iPhone user swift? - swift

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

Related

Create a clickable map preview using MKMapSnapshotter

I have a map that currently shows the user's current location with no pin to show them exactly where they are. I want to make the map a photo of where the user's set location is. I only know how to show where their device is and need them to be able to set their base of operations. I don't need specific addresses. I just need the city where they reside.
I then need the image to be able to be tapped on. When tapped, the image makes the MapKit full screen and interactive. They can then zoom around the map and see where other users' set their base of operations.
I am new to coding and can't figure out how to allow the user to set a permanent location even if they move around the country. I also don't know how to set up the mapsnapshot and on top of that expand when tapped to show a fully working map view.
I am only currently able to ask if I can activate location services and then show their map view where they are when it is loaded. Here is the code:
import UIKit
import CoreLocation
import MapKit
class HomeTableViewController: UITableViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
#IBOutlet weak var mapPreviewImageView: UIImageView!
#IBOutlet weak var mapView: MKMapView!
let manager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
manager.desiredAccuracy = kCLLocationAccuracyBest // battery
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
// Always adopt a light interface style.
overrideUserInterfaceStyle = .light
takeSnapShot()
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 7
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
manager.stopUpdatingLocation()
render(location)
}
}
func render (_ location: CLLocation) {
let coordinate = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
let region = MKCoordinateRegion(center: coordinate, span: span)
mapView.setRegion(region, animated: true)
}
func takeSnapShot() {
let location = CLLocation()
let mapSnapshotOptions = MKMapSnapshotter.Options()
let coordinate = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
let region = MKCoordinateRegion(center: coordinate, span: span)
mapSnapshotOptions.region = region
// Set the scale of the image. We'll just use the scale of the current device, which is 2x scale on Retina screens.
mapSnapshotOptions.scale = UIScreen.main.scale
// Show buildings and Points of Interest on the snapshot
mapSnapshotOptions.showsBuildings = true
mapSnapshotOptions.mapType = .satellite
let snapShotter = MKMapSnapshotter(options: mapSnapshotOptions)
snapShotter.start() { snapshot, error in
guard let snapshot = snapshot else {
return
}
self.mapPreviewImageView.image = snapshot.image
}
}
}
Thanks for your help in advance. I really need to make some progress on this app and I can't seem to find any tutorials or web results on how to do this.
Edit:
I have tried adding a function that turns my UIImage into the snapshot. I am able to return an image but it doesn't show my location and it is smaller than my UIImage. I had edited the code above to reflect the changes I made. I don't know what I am doing wrong.
In your example, you are creating a CLLocationManager, but not using it. You are using CLLocation(). That obviously has no (meaningful) coordinate associated with it. Make sure to supply a valid coordinate. For example, have didUpdateLocations call takeSnapshot:
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
private weak var snapshotter: MKMapSnapshotter?
private lazy var manager: CLLocationManager = {
let manager = CLLocationManager()
manager.delegate = self
manager.distanceFilter = 20
return manager
}()
override func viewDidLoad() {
super.viewDidLoad()
if manager.authorizationStatus == .notDetermined {
manager.requestWhenInUseAuthorization()
}
manager.startUpdatingLocation()
}
func takeSnapshot(of location: CLLocation) {
snapshotter?.cancel() // cancel prior one, if any
let options = MKMapSnapshotter.Options()
options.camera = MKMapCamera(lookingAtCenter: location.coordinate, fromDistance: 1000, pitch: 0, heading: 0)
options.mapType = .satellite
options.size = imageView.bounds.size
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.start() { snapshot, _ in
self.imageView.image = snapshot?.image
}
self.snapshotter = snapshotter
}
}
extension ViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last(where: { $0.horizontalAccuracy >= 0 } ) else { return }
takeSnapshot(of: location)
}
}
That yields:
Unrelated observations:
You are using MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1). I personally do not find spans in degrees to be terribly useful. I might advise using meters, e.g.
options.region = MKCoordinateRegion(center: location.coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)
Or use a MKMapCamera:
options.camera = MKMapCamera(lookingAtCenter: location.coordinate, fromDistance: 1000, pitch: 0, heading: 0)
There is no point in using showsBuildings if you are using a map type of satellite. The docs say:
The mapType property must be set to MKMapType.standard for extruded buildings to be displayed.
I do not believe that you have to set the scale. The docs say:
This property is set to a default value that corresponds to the resolution of the current device’s display.
Besides, this property is now deprecated, anyway.
I would suggest, though, to set the size of the image.

How can I center the map on my own position?

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:)

Fix MKPointAnnotation to centre of MapKit even while scrolling

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

swift passing data in textfield to mapview

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

Swift MapView Stuck Around User's Current Location

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