Swift 4, Xcode 9: Getting and displaying the user's location - ios

I am trying to get and display the user's location, but the simulator will only load the country I am in. I set up the required info.plist sections (privacy - location when in use and always), linked the mapView in Main.storyoard to the delegate (control-dragged to View Controller Icon), attached the IBOutlet (checked it to make sure it is properly connected) and wrote this code in viewController.swift:
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var locationManager = CLLocationManager()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
mapView.mapType = MKMapType.standard
let location = locations[0]
let myLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion(center: myLocation, span: span)
mapView.setRegion(region, animated: true)
self.mapView.showsUserLocation = true
}
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I am just getting my feet wet with MapKit and this issue has been keeping me back for quite some time. Would appreciate any help.

Please use iPhone Device to get the current location. In the simulator, you have to set location then get that location. So can do this easily using the device. Your code will work with the real device.
If you want to test it with simulator the follow https://medium.com/#abhimuralidharan/location-simulation-in-xcode-ff7db9042710

Related

Why my app crashes when loading a MapKit View in disconnected from computer iPhone?

I have a UIViewController with a MapKit View inside of it, the app runs perfectly in simulator and physical device connected to my mac, but when I try to run the app with the device disconnected, it crashes when going to the MapKit View
I Tried to make the MapKit View the initial View Controller
I tried to reset my phone
I tried to reset Xcode
import UIKit
import ChameleonFramework
class PanicMapViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = FlatYellowDark()
configureNavigationBar()
}
func configureNavigationBar() {
navigationController?.navigationBar.barTintColor = FlatYellowDark()
navigationController?.navigationBar.barStyle = .black
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor:ContrastColorOf(FlatYellowDark(),returnFlat: true)]
navigationItem.title = "Side Menu"
}
}
I expect that when my physical device is disconnected I can run the app and see the MapKit view.
I was having this problem (Xcode 11 building for iOS 12.4) and stumbled across this question whilst looking for a solution.
For me, I resolved the problem by adding 'Maps' as a 'Capability' under the 'Signing and Capabilities' tab of the project file.
You need to
import MapKit
Inside PanicMapViewController
I was having same issue. even after typing import MapKit.
i did some research and found out the device was not able to find current location.
import UIKit
import MapKit
Class PSSearchVC: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet var mapview: MKMapView!
let locationmanager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
mapview.mapType = MKMapType.standard
let location = CLLocationCoordinate2DMake(22.4651, 70.0771)
let span = MKCoordinateSpan.init(latitudeDelta: 0.01, longitudeDelta:
0.01)
let coordinate = CLLocationCoordinate2D.init(latitude: 21.282778, longitude: -157.829444) // provide you lat and long
let region = MKCoordinateRegion.init(center: coordinate, span: span)
mapview.setRegion(region, animated: true)
let annonation = MKPointAnnotation()
annonation.coordinate = location
annonation.title = "Chandi Bazar"
annonation.subtitle = "Jamnagar"
//
mapview.addAnnotation(annonation)
self.locationmanager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled()
{
locationmanager.delegate = self
locationmanager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationmanager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
print("locations = \(locValue.latitude) \(locValue.longitude)")
locationmanager.stopUpdatingLocation()
}
}

update center of screen with current location

I have successfully made an app that shows a blinking blue dot where the user currently is. However as of right now the center of the screen does not follow the blue dot as the user moves, so if the user moves the blue dot just exits the screen and the user would have to scroll to keep up with it. That isnt user friendly! I have the below code:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
var mapp = MKMapView.self
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if (CLLocationManager.locationServicesEnabled())
{
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.map.showsUserLocation = true
}
else
{
print("Location services are not enabled")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.002, longitudeDelta: 0.002))
self.map.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
}
My only thoughts are that I could get rid of the "stopUpdatingLocation() section and maybe then it would continuously update the region with the new center for every new location, however I am not sure if not having the stopUpdatingLocation is bad practice? Thanks for all advice!
Use userTrackningMode which causes the map view to center the map on that location and begin tracking the user’s location. If the map is zoomed out, the map view automatically zooms in on the user’s location, effectively changing the current visible region.
To use it
mapView.setUserTrackingMode(.follow, animated:true)

Can't display user current location Mapbox iOS API

I want to display user's current location immediately after they open the app. I use Mapbox iOS SDK. But it doesn't work at all. I don't know what's wrong. I can only see an irrelevant map after I open it.
import UIKit
import Mapbox
import CoreLocation
class ViewController: UIViewController, MGLMapViewDelegate, CLLocationManagerDelegate
{
#IBOutlet weak var mapView: MGLMapView!
let locationManager = CLLocationManager()
override func viewDidLoad()
{
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: Location Delegate Methods
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations.last
let mapView = MGLMapView(frame: view.bounds)
mapView.userTrackingMode = .Follow
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
mapView.setCenterCoordinate(center, zoomLevel: 15, animated: true)
view.addSubview(mapView)
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
print ("Errors:" + error.localizedDescription)
}
}
I think the issue might be the iOS Simulator. When you run an app on the simulator, it doesn't simulate your location until you tell it to.
If you look at your Xcode, you'll see a navigate button at the bottom.
Try changing the location to something, and it should show up :)

How to display sub view or button on top of Google maps Xcode

I was trying to add a button on top of Google maps. i tried everything i could but no help can anyone help me.. in Xcode preview it shows on top but after running the app it come below google map.
Picture after running app
How it looks in XCODE
CODE OF MAP
import UIKit
import GoogleMaps
class HomeViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var scrollView: UIScrollView!
#IBAction func refreshLocation(sender: AnyObject) {
locationManager.startUpdatingLocation()
}
#IBOutlet weak var gMapView: GMSMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
self.scrollView.contentSize=CGSizeMake(320, 700)
let camera = GMSCameraPosition.cameraWithLatitude(15.4989, longitude: 73.8278, zoom: 17)
gMapView.camera = camera
gMapView.myLocationEnabled = true
self.view.addSubview(gMapView)
let marker = GMSMarker()
marker.map = self.gMapView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
extension HomeViewController {
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.AuthorizedAlways {
locationManager.startUpdatingLocation()
gMapView.myLocationEnabled = true
gMapView.settings.myLocationButton = true
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
gMapView.camera = GMSCameraPosition(target: location.coordinate, zoom: 15, bearing: 0, viewingAngle: 0)
locationManager.stopUpdatingLocation()
}
}
}
I found the answer
self.view.bringSubviewToFront(self.view_name)
You need to call bringSubviewToFront on the parent view.
Are you using below method? If yes , make sure you are giving frame to mapview so try to give frame as same as you gave in storyboard.
[GMSMapView mapWithFrame:(CGRect) camera:(GMSCameraPosition *)];

Swift - map returns to starting point

I have a map in my app but when i move the map around, the second I let go, it returns to the starting point. I do not want this to happen..
My ViewController looks like this atm:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if (CLLocationManager.locationServicesEnabled())
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
}
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.map.setRegion(region, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
CLLocationManager's startUpdatingLocation sends updates to the User's location to locationManager:didUpdateLocations:.
Calling this method causes the location manager to obtain an initial location fix (which may take several seconds) and notify your delegate by calling its locationManager:didUpdateLocations: method.
So then in locationManager:didUpdateLocations: the region you're moving the map to with setRegion:animated: is the location that just got sent, i.e., the User's location.
You set the region of your mapView in the didUpdateLocations delegate method.
Once you start to call startUpdatingLocation(), it will start to keep retrieving your location coordinate, and your didUpdateLocations method will be called, and your mapView will be update by the setRegion() in your method.
You can change the value of location manager's distanceFilter to a bigger number, so it will update less frequently. By default, kCLDistanceFilterNone is used, so your didUpdateLocations will be called of all movements.
So it seems like I just had to add locationManager.stopUpdatingLocation() to the didUpdateLocations function

Resources