I am trying to create a mock up app that shows the campus of my school. I want to be able to search through the campus and then click the location button to have the screen follow my location. Check video below to understand my issue. My code is proprietary as i am brand new to swift and xcode. I am not using the story board, just programatically creating this app. When i do get the location to consistently update my location and follow my simulation location, it tears down the view and rebuilds it, which leads to it looking very glitchy. Also, i cannot break the update by changing moving the camera somewhere else. Im sure im missing something quite big. To make as much sense as possible, i want to be able to follow the location on screen in a smooth look, as well as stop the updating location so that can search the campus without my screen updating to my current location.
video link: [https://www.dropbox.com/s/op2kw9sfk0c8dm5/Xcode%20problem.mp4?dl=0][1]
here is my code:
import UIKit
import GoogleMaps
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate, GMSMapViewDelegate{
lazy var mapView = GMSMapView()
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
GMSServices.provideAPIKey("AIzaSyBXEZf5gq-ewIjmlzyWlsDHJSsOTsHCm4k")
let camera = GMSCameraPosition.camera(withLatitude: 35.046462, longitude: -85.298153, zoom: 15.8, bearing: 295, viewingAngle: 0)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView.mapType = .satellite
//view = mapView
//User Location
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
locationManager.stopUpdatingLocation()
view = mapView
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: 15.8, bearing: 295, viewingAngle: 0)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView.mapType = .satellite
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
showMarker(position: CLLocationCoordinate2D.init(latitude: 35.046462, longitude: -85.298153), markerTitle: "Cardiac Hill", markerSnippet: "UTC")
showMarker(position: CLLocationCoordinate2D.init(latitude: 35.047488, longitude: -85.300121), markerTitle: "Library", markerSnippet: "UTC")
view = mapView
}
func showMarker(position: CLLocationCoordinate2D, markerTitle: String, markerSnippet: String){
let marker = GMSMarker()
marker.position = position
marker.title = "\(markerTitle)"
marker.snippet = "\(markerSnippet)"
marker.tracksViewChanges = true
marker.opacity = 0.75
marker.icon = GMSMarker.markerImage(with: .white)
marker.map = mapView
}
func markerInfo(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
var view = UIView(frame: CGRect.init(x: 0, y: 0, width: 200, height: 70))
view.backgroundColor = UIColor.white
view.layer.cornerRadius = 6
let lbl1 = UILabel(frame: CGRect.init(x: 8, y: 8, width: view.frame.size.width - 16, height: 15))
lbl1.text = "Cardiac label"
view.addSubview(lbl1)
let lbl2 = UILabel(frame: CGRect.init(x: lbl1.frame.origin.x, y: lbl1.frame.origin.y + lbl1.frame.origin.y + 3, width: view.frame.size.width - 16, height: 15))
lbl1.text = "lbl2 info"
view.addSubview(lbl2)
return view
}
}
Thank you for your time, I will be sure to check this almost everyday to respond to any addition information needed. PS, i already did api and sdk importing, as well as added info into info.plist. I seem to get everything to work but this issue.
Related
I have followed GoogleMaps SDK. The map shows well. MyLocation, zoom-in, zoom-out all work well.
The issue is when I click "myLocation" button after zoom-in or zoom-out and move to other location, the map will go back to my location, BUT the zoom stays as zoom-in or zoom-out level. It doesn't get back to original zoom level. My code is as follow:
//googleMap
var locationManager = CLLocationManager()
var currentLocation: CLLocation?
var mapView: GMSMapView!
var placesClient: GMSPlacesClient!
var zoomLevel: Float = 15.0
// An array to hold the list of likely places.
var likelyPlaces: [GMSPlace] = []
// The currently selected place.
var selectedPlace: GMSPlace?
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.distanceFilter = 50
locationManager.startUpdatingLocation()
locationManager.delegate = self
let camera = GMSCameraPosition.camera(withLatitude: 43.6532,
longitude: 79.3832,
zoom: zoomLevel)
mapView = GMSMapView.map(withFrame: view.bounds, camera: camera)
mapView.settings.myLocationButton = true
mapView.settings.compassButton = true
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.isMyLocationEnabled = true
// Add the map to the view, hide it until we've got a location update.
view.addSubview(mapView)
mapView.isHidden = true
placesClient = GMSPlacesClient.shared()
}
In my CLLocationManagerDelegate I have:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location: CLLocation = locations.last!
print("Location: \(location)")
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude,
longitude: location.coordinate.longitude,
zoom: zoomLevel)
mapView.camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude,
longitude: location.coordinate.longitude,
zoom: zoomLevel)
if mapView.isHidden {
mapView.isHidden = false
mapView.camera = camera
} else {
mapView.animate(to: camera)
}
}
I am trying to add Google Maps view as a subview of the UIViewController. But it is giving an infinite loop calling viewDidLoad(). How to fix this?
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: 53.9, longitude: 27.5667, zoom: 6)
mapView = GMSMapView.map(withFrame: CGRect(x: 100, y: 100, width: 200, height: 200), camera: camera)
mapView?.center = self.view.center
self.view.addSubview(mapView!)
}
I am creating UIViewController programatically and adding the below code fixed the issue.
override func loadView() {
let screenSize = UIScreen.main.bounds
view = UIView(frame: CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height))
view.backgroundColor = UIColor.white
}
override func loadView() {
//Call the map
let camera = GMSCameraPosition.camera(withLatitude: "your latitude", longitude: "longitute", zoom: 15.0)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView.delegate = self
self.view = mapView
mapView.settings.myLocationButton = true // enable current location button on map
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.isMyLocationEnabled = true
}
How to create a function for drawing markers on a map from an array of applications received during the operation. That is, the function must be outside the viewDidLoad() ?
If you use a simple function with the following content:
import UIKit
import GoogleMaps
import CoreLocation
class ViewController: UIViewController {
#IBOutlet var mMap: GMSMapView!
let locationManager = CLLocationManager()
let mapInsets = UIEdgeInsets(top: 10.0, left: 0.0, bottom: 100.0, right: 0.0)
override func viewDidLoad() {
super.viewDidLoad()
view = mMap
mMap.padding = mapInsets
mMap.isMyLocationEnabled = true
mMap.settings.compassButton = true
mMap.settings.myLocationButton = true
mMap.settings.scrollGestures = true
mMap.settings.zoomGestures = true
let camera = GMSCameraPosition.camera(withLatitude: myLat, longitude: myLon, zoom: 15.0)
let mMap = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
let buttonDps = UIButton(frame: CGRect(x: 2, y: 520, width: 103, height: 45))
button.backgroundColor = .red
button.setTitle("yes", for: .normal)
button.titleLabel!.font = UIFont.boldSystemFont(ofSize: 19)
button.layer.cornerRadius = 5.0
button.addTarget(self, action: #selector(buttonAct), for:.touchUpInside)
self.view.addSubview(button)
}
func buttonAct(sender: UIButton!) {
let alert = UIAlertController(title:"help", message:"qwerty", preferredStyle:.alert)
alert.addAction(UIAlertAction(title:"OK", style:.default){ action in
self.markercreate()
})
alert.addAction(UIAlertAction(title:"cancel", style:.cancel, handler:nil))
self.present(alert, animated:true, completion:nil)
}
func markercreate(){
let marker2 = GMSMarker()
marker2.position = CLLocationCoordinate2D(latitude: 54.9044200, longitude: 52.3154000)
marker2.title = "Россия"
marker2.snippet = "Москва"
marker2.map = mMap
}
}
then nothing happens (((
Suppose you have a list of latitude, longitude and place name.
Create a loop and inside your loop if you want to show markers then use this.
func createMarker()
{
let lon = Double(longResult as! String)
let lat = Double(latResult as! String)
print("Center_Name: \(centerName)")
print("Longitude: \(longResult)")
print("Latitude: \(latResult)")
let markerResult = GMSMarker()
markerResult.position = CLLocationCoordinate2D(latitude: lat! , longitude: lon!)
markerResult.title = "\(centerName)"
markerResult.map = viewMap
}
The code I have shown is a basic one. With this you can create a marker on your map.
As far as I can analyze,
The code will work fine. Also the marker is added to the map. You just don't see the marker you have added. Move the camera position of the map to marker position so that you can see the marker, i.e.
func markercreate()
{
//Your code...
mMap.camera = GMSCameraPosition.camera(withLatitude: 54.9044200, longitude: 52.3154000, zoom: 15.0) //Add this line to your code
}
I assume you will resolve the 2 mMap variables that you have created as I mentioned in the comment.
Edit:
1. In Storyboard, set the ViewController's view's class to GMSMapView and connect the outlet mMap to it, i.e.
2. Follow the comments in the below code snippet:
override func viewDidLoad()
{
super.viewDidLoad()
//Your code...
view = mMap //Remove this line
mMap.camera = GMSCameraPosition.camera(withLatitude: 54.9044200, longitude: 52.3154000, zoom: 15.0) //Add this line
let camera = GMSCameraPosition.camera(withLatitude: myLat, longitude: myLon, zoom: 15.0) //Remove this line
let mMap = GMSMapView.map(withFrame: CGRect.zero, camera: camera) //Remove this line
//Your code...
}
import UIKit
import GoogleMaps
import FirebaseDatabase
import GeoFire
class MapViewController: UIViewController, CLLocationManagerDelegate, GMSMapViewDelegate {
var mapView = GMSMapView()
var locationManager: CLLocationManager!
let regionRadius: CLLocationDistance = 1000
var place = CLLocationCoordinate2D()
#IBOutlet var myLocationButton: UIButton!
#IBOutlet var infoWindow: UIView!
#IBOutlet var postTitle: UILabel!
#IBOutlet var postImage: UIImageView!
var showing = false;
var pins = [String: Pin]()
var currentMarker = GMSMarker()
override func viewDidLoad() {
super.viewDidLoad()
// sets up the map view (camera, location tracker etc.)
let camera = GMSCameraPosition.camera(withLatitude: place.latitude, longitude: place.longitude, zoom: 17.0)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView.isMyLocationEnabled = true
mapView.delegate = self
view = mapView
self.view.addSubview(myLocationButton)
self.view.bringSubview(toFront: myLocationButton)
// Location manager
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
locationManager.startUpdatingLocation()
// Get nearby records
let geoFire = GeoFire(firebaseRef: FIRDatabase.database().reference().child("geofire"))
let query = geoFire?.query(at: CLLocation(latitude: place.latitude, longitude: place.longitude), withRadius: 0.6)
_ = query?.observe(.keyEntered, with: { (key, location) in
let marker = GMSMarker()
let newPin = Pin(title: "post", locationName: "\(key!)", discipline: "", coordinate: (location?.coordinate)!)
self.pins[newPin.locationName] = newPin
marker.icon = UIImage(named: "icon_small_shadow")
marker.position = Pin.coordinate
marker.title = Pin.title
marker.snippet = Pin.locationName
marker.map = mapView
})
myLocationTapped(myLocationButton)
}
// sets the info in the custom info window
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
if(currentMarker == marker && showing) {
infoWindow.isHidden = true
showing = false
} else {
infoWindow.isHidden = false
self.view.addSubview(infoWindow)
self.view.bringSubview(toFront: infoWindow)
postTitle.text = marker.snippet
showing = true
}
currentMarker = marker
return true
}
#IBAction func myLocationTapped(_ sender: Any) {
print("tapped")
let cameraPosition = GMSCameraPosition.camera(withLatitude: place.latitude, longitude: place.longitude, zoom: 15.0)
mapView.animate(to: cameraPosition)
}
I have the following code set up, designed to place a button on the google maps map that when tapped, animates the google maps camera to that location. However, my code doesn't work. The "tapped" prints in the console but the camera doesn't budge. I haven't been able to find an answer anywhere for this, so any help would be appreciated.
EDIT: Added full code for the Map View Controller
In my case the map wasn't updating because I was not calling the method on the main queue. The following code solved the issue:
DispatchQueue.main.async {
self.mapView.animate(to: camera)
}
Anything action related to the user interface should be called in the main queue
Try this way
let cameraPosition = GMSCameraPosition.camera(withLatitude: place.latitude, longitude: place.longitude, zoom: 15.0)
mapView.animate(to: cameraPosition)
Edit: Issue is you aren't having the reference of your map with your mapView object, change your viewDidLoad's line:
view = mapView
TO:
// sets up the map view (camera, location tracker etc.)
let camera = GMSCameraPosition.camera(withLatitude: place.latitude, longitude: place.longitude, zoom: 17.0)
let mapView = GMSMapView.map(withFrame: view.bounds, camera: camera)
mapView.isMyLocationEnabled = true
mapView.delegate = self
self.mapView = mapView
view.addSubview(self.mapView)
I am trying to set a GoogleMap to a UIView and add it as a Subview. However, when running the app I get this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
It crashes at code line:
mapView.camera = camera
Here's my full ViewController code:
class LocationViewController: UIViewController {
#IBOutlet weak var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: 15.4989, longitude: 73.8278, zoom: 6)
mapView.camera = camera
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
self.view.addSubview(self.mapView)
}
}
I went through a few other similar SO threads and all of them have the same code. In my case the UI freezes and crashes with this error. What am I doing wrong?
EDIT
Yes, I have set the UIView's custom class as GMSMapView
Could you please use below code and try:
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: 15.4989, longitude: 73.8278, zoom: 6)
mapView.camera = camera
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
self.view.addSubview(self.mapView)
}
you have to do it like this
you have to give frame to GMSMapview
Here in this line self.view.bounds , you have to set your custom view
let camera = GMSCameraPosition.camera(withLatitude: 15.4989,
longitude: 73.8278,
zoom: 6)
let mapView = GMSMapView.map(withFrame: self.view.bounds, camera: camera)
This is the syntax in swift 3.0
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
print(locations)
mapview.delegate = self
currentLocation = CLLocationCoordinate2D(latitude:CLLocationDegrees(locations[0].coordinate.latitude), longitude:CLLocationDegrees(locations[0].coordinate.longitude))
mapview.camera = GMSCameraPosition.camera(withTarget:locations[0].coordinate, zoom: 10.0)
mapview.isMyLocationEnabled = true
}