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
}
Related
Here is my code:
let camera = GMSCameraPosition.camera(withLatitude: 51.5, longitude: -0.127, zoom: 12.0)
var mainView:UIView = GMSMapView.init(frame: CGRect(x:50,y:150,width:250,height:300))
self.view.addSubview(mainView)
let mapView = GMSMapView.map(withFrame: mainView.frame, camera: camera)
mainView = mapView
//Marker Position
let position = CLLocationCoordinate2D(latitude: 51.5, longitude: -0.127)
let london = GMSMarker(position: position)
london.title = "London"
london.icon = UIImage(named: "house")
london.map = mapView
Replace
var mainView:UIView = GMSMapView.init(frame: CGRect(x:50,y:150,width:250,height:300))
self.view.addSubview(mainView)
let mapView = GMSMapView.map(withFrame: mainView.frame, camera: camera)
mainView = mapView
with
var mainView:GMSMapView! // instance var
// in viewDidLoad
let camera = GMSCameraPosition.camera(withLatitude: 51.5, longitude: -0.127, zoom: 12.0)
mainView = GMSMapView.map(withFrame:CGRect(x:50,y:150,width:250,height:300), camera: camera)
mapView.delegate = self
self.view.addSubview(mainView)
I'm displaying map in my view. I'm using auto layout, that's why i called create map view function in viewDidLayoutSubviews(). viewDidLayoutSubviews() Called two times and map created two times, but initial map not removed from the view. When i call create map view function in viewDidLoad() it's creating only one time and it's not fit in to the view frame.
My code is...
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("viewDidLayoutSubviews")
loadMapView()//Call map view function
let width = mapSubView.frame.size.width
let x = mapSubView.frame.minX
let y = mapSubView.frame.minY
searchBar.frame = CGRect(x: x+10, y: y+10, width: width, height: 40)
mapSubView.addSubview(searchBar)
searchBar.delegate = self
// hide cancel button
searchBar.showsCancelButton = true
// set Default bar status.
searchBar.searchBarStyle = UISearchBarStyle.default
let y1 = searchBar.frame.maxY
searchTableView.frame = CGRect(x: x, y: y1, width: width, height: searchTableView.frame.size.height)
mapSubView.addSubview(searchTableView)
searchTableView.delegate = self
searchTableView.dataSource = self
}
//Create map view
func loadMapView() {
// Create a GMSCameraPosition that tells the map to display the
// coordinate -33.86,151.20 at zoom level 6.
let camera = GMSCameraPosition.camera(withLatitude: 19.3822559, longitude: 80.2194394, zoom: 6.0)
let mapView = GMSMapView.map(withFrame: CGRect(x: 1, y: 1, width: mapSubView.frame.size.width-2, height: mapSubView.frame.size.height-2), camera: camera)
mapSubView.addSubview(mapView)
print("map : \(mapSubView.frame.size.height)")
print("map : \(mapView)")
// Creates a marker in the center of the map.
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: 19.3822559, longitude: 80.2194394)
marker.title = ""
marker.snippet = ""
marker.map = mapView
}
How to fit map in my mapSubView?
Embed the code inside once var
var once = true
//
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("viewDidLayoutSubviews")
if once {
loadMapView()//Call map view function
let width = mapSubView.frame.size.width
let x = mapSubView.frame.minX
let y = mapSubView.frame.minY
searchBar.frame = CGRect(x: x+10, y: y+10, width: width, height: 40)
mapSubView.addSubview(searchBar)
searchBar.delegate = self
// hide cancel button
searchBar.showsCancelButton = true
// set Default bar status.
searchBar.searchBarStyle = UISearchBarStyle.default
let y1 = searchBar.frame.maxY
searchTableView.frame = CGRect(x: x, y: y1, width: width, height: searchTableView.frame.size.height)
mapSubView.addSubview(searchTableView)
searchTableView.delegate = self
searchTableView.dataSource = self
once = false
}
}
or use constraints in viewDidLoad
mapView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate( [
mapView.leadingAnchor.constraint(equalTo: mapSubView.leadingAnchor, constant: 0),
mapView.trailingAnchor.constraint(equalTo: mapSubView.trailingAnchor, constant: 0),
mapView.topAnchor.constraint(equalTo: mapSubView.topAnchor, constant: 0),
mapView.bottomAnchor.constraint(equalTo: mapSubView.bottomAnchor, constant: 0),
])
I am having an issue that GMSMarker changes camera focus on any kind of popup alert or whenever I tap on marker and app navigates to google maps application. Following is my implementation. I add google maps container to my viewcontroller header in layoutsubviews method. No idea what's going on. Kindly help.
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
if mapView == nil
{
let camera = GMSCameraPosition.camera(withLatitude: 45.582045, longitude:74.32937, zoom: 14.0)
mapView = GMSMapView.map(withFrame: CGRect(x: 0, y: 0, width: self.mapContainerView.bounds.size.width, height: self.mapContainerView.bounds.size.height), camera: camera)
mapView.delegate = self
do {
// Set the map style by passing the URL of the local file.
if let styleURL = Bundle.main.url(forResource: "style", withExtension: "json") {
mapView.mapStyle = try GMSMapStyle(contentsOfFileURL: styleURL)
} else {
NSLog("Unable to find style.json")
}
} catch {
NSLog("One or more of the map styles failed to load. \(error)")
}
self.mapContainerView.addSubview(mapView)
mapView.settings.setAllGesturesEnabled(false)
let marker = AppointmentMapDataManager(mapView: mapView).setAppointmentMarker()
// let location = GMSCameraPosition.camera(withLatitude: marker.position.latitude,
// longitude: marker.position.longitude,
// zoom: 14)
// mapView.camera = location
var bounds = GMSCoordinateBounds()
bounds = bounds.includingCoordinate((marker as AnyObject).position)
let update = GMSCameraUpdate.fit(bounds, with: UIEdgeInsets(top: self.mapContainerView.frame.height/2 - 33, left: self.mapContainerView.frame.width/2 - 81, bottom: 0, right: 0))
mapView.moveCamera(update)
}
}
Instead of move your camera in the viewDidLayoutSubView which is a wrong approach use didTap method of the GMSMapViewDelegate or if you want to do it automatically use a execute after delay
//method for center camera based in your own code
func centerInMarker(marker: GMSMarker) {
var bounds = GMSCoordinateBounds()
bounds = bounds.includingCoordinate((marker as AnyObject).position)
let update = GMSCameraUpdate.fit(bounds, with: UIEdgeInsets(top: (self.mapView?.frame.height)!/2 - 33, left: (self.mapView?.frame.width)!/2 - 81, bottom: 0, right: 0))
mapView?.moveCamera(update)
}
You can use it in the delegate method
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
self.centerInMarker(marker: marker)
return true
}
Or simply when you add your marker, with delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.centerInMarker(marker: marker)
}
You should add in viewDidLoad method, and update frame in viewDidLayoutSubviews.
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.
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...
}