when getting dynamic google map with using GMSMap the map doesn't show the current location that i gave him and not zoom the map
import UIKit
import GoogleMaps
import MapKit
class LocationItemViewController: UIViewController,GMSMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var lblInfo: UILabel!
#IBOutlet weak var lblTitle: UILabel!
#IBOutlet weak var viewMap: UIView!
#IBOutlet weak var googleMapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
let latitude = (String(format:"%.02f", locationItem.itemLatitude ) as NSString).doubleValue
let longgitude = (String(format:"%.02f", locationItem.itemLongitude) as NSString).doubleValue
let camera = GMSCameraPosition.cameraWithLatitude(latitude,longitude: longgitude, zoom: 7)
let mapView = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
mapView.myLocationEnabled = true
self.googleMapView = mapView
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake((locationItem.itemLatitude as NSString).doubleValue, (locationItem.itemLongitude as NSString).doubleValue)
marker.title = "somelocation"
marker.snippet = "anywhere"
marker.map = mapView
lblTitle.text = locationItem.itemName
lblInfo.text = locationItem.itemAddress
}
I was locate the GMSServices.provideAPIKey("YOUR_API_KEY") in app delegate
To display your current location you have to do the same thing which we do for apple maps to access our location.
In plist you have to add 2 entries and take permission from User
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
Check this link for more details iOS 8 CLLocationManagerDelegate methods are never called
Now regarding your google maps zoom issue
var mapView:GMSMapView?
Now in your viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
GMSServices.provideAPIKey("YOUR_API_KEY")
//Taking HardCoded lat longs for the time being. These lat longs are of New Delhi, India
let camera = GMSCameraPosition.cameraWithLatitude(28.6139, longitude: 77.2090, zoom: 10)
mapView = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
mapView!.myLocationEnabled = true
self.view = mapView
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(28.6139, 77.2090)
marker.title = "Delhi"
marker.snippet = "India"
marker.map = mapView
//As view takes some time to load so I am calling my zoom function after a delay of 1 second. You can use the zoom function code in viewDidAppear too
//Also this syntax is the latest Swift 2.2 syntax. If you are using the old Swift version, make the changes accordingly for performSelector method
self.performSelector(#selector(zoom), withObject: nil, afterDelay: 1.0)
}
Here is the zoom method
func zoom() {
CATransaction.begin()
CATransaction.setValue(1, forKey: kCATransactionAnimationDuration)
// It will animate your camera to the specified lat and long
let camera = GMSCameraPosition.cameraWithLatitude(28.6139, longitude: 77.2090, zoom: 15)
mapView!.animateToCameraPosition(camera)
CATransaction.commit()
}
Related
PNG Tiles are showing incorrect color and transparency on iOS. Transparent areas show up as a semi-transparent white. The same tile set shows up correctly on Android and web browser, so I don't believe it is an issue is with the tiles themselves. Here's my Swift code:
class ViewController: UIViewController {
#IBOutlet weak var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: 30.00, longitude: -90, zoom: 7.0)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
view = mapView
// Implement GMSTileURLConstructor
let urls: GMSTileURLConstructor = { (x, y, zoom) in
let url = "https://aerocast.s3.amazonaws.com/radar/klix/lixtileskml/\(zoom)/\(x)/\(y).png"
return URL(string: url)
}
let tilelayer = GMSURLTileLayer(urlConstructor: urls)
tilelayer.zIndex = 100
tilelayer.map = mapView
tilelayer.opacity = 1.0
}
}
I've looked for some way to adjust the color properties of the tilelayer, but have not been able to find anything.
The issue was specific to the iOS emulator on xcode. The issue is not present on a physical iOS device. I brought up the problem to Google Maps support and they were able to replicate the problem and are looking into it.
I think there is some problem with view hierarchy
class ViewController: UIViewController {
#IBOutlet weak var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: 30.00, longitude: -90, zoom: 7.0)
self.mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
self.view.addSubview(mapView)
// Define constraints (i.e position in the parent view), example for full screen ones
mapView.translatesautoresizingmaskintoconstraints = false
mapView.topAnchor.constraint(equalToSystemSpacingBelow: view.topAnchor).isActivate = true
mapView.bottomAnchor.constraint(equalToSystemSpacingBelow: view.bottomAnchor).isActivate = true
mapView.leftAnchor.constraint(equalToSystemSpacingBelow: view.leftAnchor).isActivate = true
mapView.rightAnchor.constraint(equalToSystemSpacingBelow: view.rightAnchor).isActivate = true
// Implement GMSTileURLConstructor
let urls: GMSTileURLConstructor = { (x, y, zoom) in
let url = "https://aerocast.s3.amazonaws.com/radar/klix/lixtileskml/\(zoom)/\(x)/\(y).png"
return URL(string: url)
}
let tilelayer = GMSURLTileLayer(urlConstructor: urls)
tilelayer.zIndex = 100
tilelayer.map = mapView
tilelayer.opacity = 1.0
}
}
I am trying to add multiple Markers on Googlemaps in my app.
In the viewcontrolller under viewDidLoad I am able to load the map and a single marker.
override func viewDidLoad() {
super.viewDidLoad()
title = NSLocalizedString("section_map", comment: "test")
let camera = GMSCameraPosition.camera(withLatitude: 48.7784, longitude:9.18121, zoom: 12)
let mapView = GMSMapView.map(withFrame: .zero, camera: camera)
view = mapView
mapView.settings.myLocationButton = true
mapView.delegate = self
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: 48.7784,longitude: 9.18121)
marker.title = "title"
marker.snippet = "snipple"
marker.icon = UIImage(named:"pin_you")
marker.map = mapView
mapData()
}
It call mapData() and from there is json file is generated
after parsing setPin is called to set the markers
func setPin(){
DispatchQueue.main.async {
for item in self.mapItems {
print (" \(item.name) \(item.marker) \(item.latitude) \(item.longitude)")
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: item.latitude,longitude: item.longitude)
marker.title = item.name
marker.snippet = item.fulladdress
var iconImage: String
switch (item.marker){
case 1:
iconImage = "pin_silver"
case 2:
iconImage = "pin_blue"
case 3:
iconImage = "pin_gold"
case 6:
iconImage = "pin_you"
default:
iconImage = "pin_silver"
}
marker.icon = UIImage(named:iconImage)
marker.map = self.mapView
}
}
}
The pins are not shown.
The print in for item in self.mapItems shows
Position number A 1 48.76947562 9.15440351
Position number B 1 48.75716485 9.17081058
Position number C 1 48.81191625 9.22752149
Position number D 2 48.81192516 9.22766708
this means all the proper data is available.
However the map is there the one pin made in viewDidLoad
The Markers in function setPin are not shown or maybe not set.
Does any-one have an idea?
I have solved it in have changed the mapData(mapView: GMSMapView!) also for setPin(mapView: GMSMapView!)
func setpin(mapView: GMSMapView!){
DispatchQueue.main.async {
for item in self.mapItems {
print (" \(item.name) \(item.marker) \(item.latitude) \(item.longitude)")
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: item.latitude,longitude: item.longitude)
marker.title = item.name
marker.snippet = item.fulladdress
var iconImage: String
switch (item.marker){
case 1:
iconImage = "pin_silver"
case 2:
iconImage = "pin_blue"
case 3:
iconImage = "pin_gold"
case 6:
iconImage = "pin_you"
default:
iconImage = "pin_silver"
}
marker.icon = UIImage(named:iconImage)
marker.map = mapView
}
}
}
Clustering your markers, you can put a large number of markers on a map without making the map hard to read. The marker clustering utility helps you manage multiple markers at different zoom levels.
For the full code sample, see the ObjCDemoApp and SwiftDemoApp on GitHub.
To add a simple marker clusterer.
/// Point of Interest Item which implements the GMUClusterItem protocol.
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
var name: String!
init(position: CLLocationCoordinate2D, name: String) {
self.position = position
self.name = name
}
}
The following code creates a cluster manager using the GMUNonHierarchicalDistanceBasedAlgorithm and the MUDefaultClusterRenderer that are included in the utility library:
class ViewController: UIViewController, GMUClusterManagerDelegate,
GMSMapViewDelegate {
private var mapView: GMSMapView!
private var clusterManager: GMUClusterManager!
override func viewDidLoad() {
super.viewDidLoad()
// Set up the cluster manager with the supplied icon generator and
// renderer.
let iconGenerator = GMUDefaultClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = GMUDefaultClusterRenderer(mapView: mapView,
clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm,
renderer: renderer)
// Generate and add random items to the cluster manager.
generateClusterItems()
// Call cluster() after items have been added to perform the clustering
// and rendering on map.
clusterManager.cluster()
}
}
Feed your markers into the cluster as GMUClusterItem objects by calling clusterManager:addItem:. The following code randomly generates cluster items (POIs) within the scope of the map's camera, then feeds them to the cluster manager:
/// Randomly generates cluster items within some extent of the camera and
/// adds them to the cluster manager.
private func generateClusterItems() {
let extent = 0.2
for index in 1...kClusterItemCount {
let lat = kCameraLatitude + extent * randomScale()
let lng = kCameraLongitude + extent * randomScale()
let name = "Item \(index)"
let item =
POIItem(position: CLLocationCoordinate2DMake(lat, lng), name: name)
clusterManager.addItem(item)
}
}
/// Returns a random value between -1.0 and 1.0.
private func randomScale() -> Double {
return Double(arc4random()) / Double(UINT32_MAX) * 2.0 - 1.0
}
Handle events on markers and clusters
class ViewController: UIViewController, GMUClusterManagerDelegate, GMSMapViewDelegate {
private var mapView: GMSMapView!
private var clusterManager: GMUClusterManager!
override func viewDidLoad() {
super.viewDidLoad()
// ... Rest of code omitted for easy reading.
// Register self to listen to both GMUClusterManagerDelegate and
// GMSMapViewDelegate events.
clusterManager.setDelegate(self, mapDelegate: self)
}
// MARK: - GMUClusterManagerDelegate
func clusterManager(clusterManager: GMUClusterManager, didTapCluster cluster: GMUCluster) {
let newCamera = GMSCameraPosition.cameraWithTarget(cluster.position,
zoom: mapView.camera.zoom + 1)
let update = GMSCameraUpdate.setCamera(newCamera)
mapView.moveCamera(update)
}
// MARK: - GMUMapViewDelegate
func mapView(mapView: GMSMapView, didTapMarker marker: GMSMarker) -> Bool {
if let poiItem = marker.userData as? POIItem {
NSLog("Did tap marker for cluster item \(poiItem.name)")
} else {
NSLog("Did tap a normal marker")
}
return false
}
}
For more Details please follow the Here
Disclaimer: very beginner level coder here, so excuse any "obvious" mistakes.
I am trying to build an app that shows to user how close they are to a marker.
I have a GoogleMaps map view and I want to refresh user location continuously (every say 3 seconds). calculate and print its linear distance (in meters) from the marker, and set that to my left navigation item button.
I tried doing this through GoogleMaps to no avail. So tried with CLLocation and CoreLocation.
Problem is, I get first value in meters (15m), second value (9m) 3 seconds later, then every other 3 second iteration of my timer only gives 9m forever, no matter if I move around (and my googlemaps view does update successfully the blue user position dot as I move around, laptop and linked ipad in hand).
What I am doing is have my timer fire off "findDistance" function every 3 seconds. The "findDistance" function runs locationmanager (which sets globalUserLocation to current one - if I am not doing something wrong), calculates distance and sets it to GlobalDistance, then updates the left navigation button item to that new distance.
But it seems like the user location is only updated twice (instead of every 3 seconds, forever).
What am I doing wrong? Any help would be greatly appreciated
I have added all the plist requirements, and here is my code:
import UIKit
import GoogleMaps
import CoreLocation
import MapKit
class googleMaps: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
let locationmanager = CLLocationManager()
var globalDistance: CLLocationDistance = 0
var mapView: GMSMapView? = nil
var globalUserLocation = CLLocation(latitude: 40.085260, longitude: 22.601468)
override func viewDidLoad() {
super.viewDidLoad()
let timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(googleMaps.findDistance), userInfo: nil, repeats: true)
self.locationmanager.delegate = self
self.locationmanager.desiredAccuracy = kCLLocationAccuracyBest
self.locationmanager.startUpdatingLocation()
timer.fire()
GMSServices.provideAPIKey("**mykeyhere**")
let camera = GMSCameraPosition.camera(withLatitude: 40.085260 , longitude: 22.601468, zoom: 40)
mapView = GMSMapView.map(withFrame: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 200, height: 500)), camera: camera)
mapView?.isMyLocationEnabled = true
view = mapView
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "\(globalDistance)", style: UIBarButtonItemStyle.plain, target: self, action: #selector(googleMaps.next as (googleMaps) -> () -> ()))
mapView?.mapType = kGMSTypeNormal
self.mapView?.settings.myLocationButton = true
self.mapView?.settings.compassButton = true
}
func locationmanager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
globalUserLocation = locations.last!
}
func findDistance(){
locationmanager
let currentLat = locationmanager.location!.coordinate.latitude
let currentLong = locationmanager.location!.coordinate.longitude
globalUserLocation = CLLocation(latitude: currentLat, longitude: currentLong)
let myMarker = CLLocation(latitude: 40.085260, longitude: 22.601468)
if globalUserLocation != nil {
let distance = globalUserLocation.distance(from: myMarker)
print(distance)
globalDistance = distance
navigationItem.leftBarButtonItem?.title = "\(globalDistance)"
}
}
I'm using Google Maps in Swift and in ViewDidLoad.
I am providing this code:
let camera: GMSCameraPosition = GMSCameraPosition.cameraWithLatitude(48.857165, longitude: 2.354613, zoom: 8.0)
mapView1.camera = camera
However, when executing the program, the camera is not updating. I am using
#IBOutlet weak var mapView1: GMSMapView
and have hooked it up with the outlet correctly
You need to implement
mapView1.animateToCameraPosition(camera)
some times in viewDidload the views cant update its changes, so you can update camera or animate camera in vewWillappear
override func viewWillAppear(_ animated: Bool) {
let camera = GMSCameraPosition.camera(withLatitude: 48.857165,
longitude: 2.354613,
zoom: 8)
mapView.camera = camera
}
I call animateWithCameraUpdate on a GMSMapView expecting it to change the map view to show the new GMSCoordinateBounds but it has no effect.
My map loads in a UICollectionViewReusableView to initially display Western Europe:
#IBOutlet weak var mapView: GMSMapView!
var fetchedResultsController : NSFetchedResultsController!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let camera = GMSCameraPosition.cameraWithLatitude(51.48, longitude: 0, zoom: 4)
mapView.camera = camera
}
I then call a function to query all my locations and update the GMSMapView to show all my locations:
func plotAll(){
let bounds = GMSCoordinateBounds.init()
for property in fetchedResultsController.fetchedObjects!
{
let capitalAsset : CapitalAsset = property as! CapitalAsset
let marker = GMSMarker.init()
marker.draggable = false
marker.snippet = capitalAsset.address
let location = CLLocationCoordinate2DMake(Double(capitalAsset.latitude!), Double(capitalAsset.longitude!))
marker.position = location
marker.map = mapView
// Update bounds to include marker
bounds.includingCoordinate(marker.position)
}
mapView.animateWithCameraUpdate(GMSCameraUpdate.fitBounds(bounds, withPadding: 50.0))
}
My plotAll function is successfully called and loops through a dozen global locations adding these to the GMSCoordinateBounds.
But the map is not being updated. I was expecting the map view to change when I called animateWithCameraUpdate but it has no effect.
Further information, for debugging I replaced the line
mapView.animateWithCameraUpdate(GMSCameraUpdate.fitBounds(bounds, withPadding: 50.0))
with :
let camera = GMSCameraPosition.cameraWithLatitude(51.48, longitude: 0, zoom: 10)
mapView.camera = camera
This does update my map view so there is no problem with calling my plotAll function, the issue is probably in my use of animateWithCameraUpdate.
I got this to work by replacing :
mapView.animateWithCameraUpdate(GMSCameraUpdate.fitBounds(bounds, withPadding: 50.0))
with:
let camera = mapView.cameraForBounds(bounds, insets:UIEdgeInsetsZero)
mapView.camera = camera;