I want to create a draggable marker but it doesn't work. What am I missing?
let marker = NMAMapMarker(geoCoordinates: coordinates, image: markerImage!)
marker.isDraggable = true
mapView.add(mapObject: maker)
mapView.respond(to: .markerDragBegan) { (drag, map, marker) -> Bool in
return true
Please take a reference from below sample code. Also share the error logs that you got while using above code snippet.
/**
* create a NMAMapMarker object, then add it to current active map view.
*/
- (void)addMapMarker {
//create NMAImage with local cafe.png
NMAImage* markerImage = [NMAImage imageWithUIImage:[UIImage imageNamed:#"cafe.png"]];
//create NMAMapMarker located with geo coordinate and icon image
NMAMapMarker* mapMarker = [NMAMapMarker mapMarkerWithGeoCoordinates:self.mapView.geoCenter icon:markerImage];
//make marker able to receive dragging gesture from map
mapMarker.draggable = YES;
//add NMAMapMarker to map view
[self.mapView addMapObject:mapMarker];
//add view and handlers for *MarkerDrag* events:
[self setupMapMarkerEventHandlersIfNeeded];
[_mapMarkers addObject:mapMarker];
}
Related
I want to show multiple annotations at once in Mapbox (note: NOT MKMap). There doesn't seem to be a method to show multiple annotations, although it can add multiples.
e.g.
mapView.addAnnotations(<annotationsArray>)
Even though there is a method as follows, it does not show the annotations.
mapView.showAnnotations(<annotationsArray>, animated: true)
What I want it to show multiple instances as shown in the image below. i.e. I want to show several "Hello World" annotations in the map, for each point the user added.
Is there a similar method in Mapbox to show multiple annotations in Swift?
Use this to display multiple annotations:
func setAnnotations() {
var index = 0
for placeModel in self.placesList! {
let marker = MyMGLPointAnnotation()
marker.willUseImage = true
marker.id = placeModel.id
marker.type = placeModel.type
if let img = placeModel.images.first {
marker.imgURL = img.thumbnail
}
marker.coordinate = CLLocationCoordinate2D(latitude: placeModel.location?.latitude ?? 0, longitude: placeModel.location?.longitude ?? 0)
marker.title = placeModel.name.withoutHtmlTags
marker.subtitle = placeModel.descr.htmlToString
//DispatchQueue.main.async {
self.mapView.setCenter(CLLocationCoordinate2D(latitude: latitude, longitude: longitude), zoomLevel: 12, animated: false)
self.mapView.addAnnotation(marker)
}
}
You can display multiple instance of the annotations but for the selection you can tap one by one and it will show title like the image you shared.
Edit: There is way you can create your custom xib load as annotation to show the title.
Check: https://github.com/mapbox/ios-sdk-examples/blob/0e2c8ce878de500f36c4168f7a1e62041c8adbdf/Examples/Swift/AnnotationViewsAndImagesExample.swift
https://docs.mapbox.com/ios/maps/examples/annotation-view-image/
I want to hide the marker after the zoom level reach 17, someone suggested I use clear method, but the issue with it that I have different marker that will show after some event so clear is not going to work any idea how can I made this possible?
To remove a specific marker
myMarker.map = nil
as far as I know there are no definite references to hiding markers, but you can manipulate marker data displayed on the map #CMIIW
as an example
var markers: [GMSMarker] = []
var tempMarker: [GMSMarker] = []
if zoom == 17 {
// TODO: Create tempMarker filter from markers
} else {
// TODO: Create tempMarker filter from markers
}
// TODO:
// mapView.clear()
// Mapview show markers from tempMarker
iOS Swift Google Maps SDK showing markers at specific zoom level?
//To delete
marker.map = nil
//to hide
marker.opacity = 0.0
I am trying to create a UITableViewCell containing a GMSMapView with a GMSMarker at the center of the current Position.
The problem is that the marker always appears at the top left corner of the current position and I don't know how to solve the problem.
I tried to follow these steps: Implementing a Google Map with UItableviewCell
here is my code from cellForRowAt:
let locationCell = tableView.dequeueReusableCell(withIdentifier: "activityLocationCell") as! ActivityLocationCell
let latitude = CLLocationDegrees(activity.coordinates![0])
let longitude = CLLocationDegrees(activity.coordinates![1])
let position = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
locationCell.googleMapView.camera = GMSCameraPosition.camera(withTarget: position, zoom: 15)
let marker = GMSMarker(position: position)
marker.groundAnchor = CGPoint(x: 0.5, y: 0.5)
marker.map = locationCell.googleMapView
return locationCell
Here is a screenshot of my problem:
marker is at the top left corner of the map
I had a pretty similar issue. I resolved it by changing the moment I configure the map in the view lifecycle.
In my case, I was using a child view controller. I was configuring the map before viewWillAppear was called which caused the map to not center properly (the marker was on the top left corner). I moved my call to after the viewWillAppear and it fixed it. A good place would be viewDidAppear.
If you are using a cell, you will probably need to investigate with the view lifecycle instead of the controller lifecycle.
This is not written anywhere on the Google documentation.
you have to draw map in
func viewDidLayoutSubviews()
Try creating Marker when map is ready completely. for eg: use the delegate.
var ifMapReady: Bool = false
...
...
func mapViewSnapshotReady(_ mapView: GMSMapView) {
ifMapReady = true
}
//Call this method from where ever you want to load map
func updateMap() {
if ifMapReady {
//Load Map
}
}
This delegate will be called multiple times(eg: map is swiped or moved etc) whenever the Map tiles are ready. So we can use a boolean value for understanding that map loaded successfully. Based on that value we can load the Map properly when initiating.
I want to add one more thing. #Gabriel Cartier's answer worked for me with one additional change in my code.
[self->mapView_ animateToCameraPosition:camera];
And I replaced with
[self->mapView_ setCamera:camera];
I have created NMAMapView object using storyboard and I am using the reference of that NMAMapView object in view controller code and added markers to it. In this case, the markers are visible on the screen
To set the zoom automatically I created NMABoundingBox, added markers to it and then set the bounding box to NMAMapView using setBoundingBox::withAnimation method.
But if I create the NMAPMapView object dynamically, set the view controller view frame to the NMAMapView and add it as a subview to view controller view and then added the markers to the view, then the markers are visible out of the map. I have to do a manual zoom out on the map to see the markers.
I have also tried using setBoundingBox::insideRect::withAnimation method of NMAMapView for the above dynamically created map scenario to set the zoom automatically. But the maps is being pointed to some random portion of the world with some inappropriate zoom.
Need resolution for this issue. Thanks
In my case, I see a marker on the map only if some image is set as an icon of NMAMapMarker. Looks like there's no default marker available.
let coordinates: NMAGeoCoordinates = ...
let image: UIImage = ...
let marker = NMAMapMarker(geoCoordinates: coordinates, image: image)
or
let coordinates: NMAGeoCoordinates = ...
let marker = NMAMapMarker(geoCoordinates: coordinates)
let image: UIImage = ...
marker.icon = NMAImage(uiImage: image)
Hopefully, it helps.
I have integrated Google Maps in my application and also using Google Places API. After I am getting all the results from Google Places API(around 60), I am displaying them with the help of custom marker. The custom marker which I am making comprises of "Place Image" and "Place Name" because of which I have to first draw it in a UIView and then render it as a UIImage with the help of following function
- (UIImage *)imageFromView:(UIView *) view
{
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, [[UIScreen mainScreen] scale]);
} else {
UIGraphicsBeginImageContext(view.frame.size);
}
[view.layer renderInContext: UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
At first all the markers are rendered and drawn easily.
Now I have a slider ranging from 100m to 5km, which acts as a search radius optimiser. As the slider will be moved(suppose to a value 2km), then all the markers are removed and only those markers whose distance from user location is less then slider value are drawn again. While I am testing the slider functionality, the application crashes saying
((null)) was false: Reached the max number of texture atlases, can not allocate more.
I am uploading screen shots for clear understanding of situation.
Please help.
Also to mention, in the screens you will see green markers as well as blue markers. Blue markers are those which are closer to user location while green ones are far off by a particular distance. As the user location will change there are 2 cases:
If it is approaching a green marker, then it will turn to a blue marker
If it is going far from a blue marker, then it will turn to a green marker.
I am working on an app which can have several thousand avatars moving around on the map and encounter this bug also. Clustering is a potential solution, but with this many avatars all moving, I suspect the calculations will be too CPU intensive.
The solution I use is to keep a reference to the base avatar image and use it when > 50 avatars are on the screen. Only when there are < 50 avatars on the screen, then I will generate unique images for each avatars with their names.
// GMSMarker
static var avatarDic:[String:UIImage] = Dictionary()
func removeName() {
// use a single image reference here so that google map does not crash
if let image = avatarDic[avatarBase] {
self.icon = image
}
else {
avatarDic[avatarBase] = UIImage(named:avatarBase)
self.icon = avatarDic[avatarBase]
}
}
func addName() {
self.icon = // draw name on base image
}
// GMSMapView
var userIcons:[String:MyMarker] = Dictionary()
var iconWithNames:Set<MyMarker> = Set()
func mapView(mapView: GMSMapView!, didChangeCameraPosition position: GMSCameraPosition!) {
// find visible avatars til limit
let bottomLeft = self.mapView.projection.visibleRegion().nearLeft
let topRight = self.mapView.projection.visibleRegion().farRight
var visibleMarkerSet:Set<MyMarker> = Set()
for (key, marker) in self.userIcons {
if (marker.position.latitude > bottomLeft.latitude && marker.position.latitude < topRight.latitude && marker.position.longitude > bottomLeft.longitude && marker.position.longitude < topRight.longitude) {
visibleMarkerSet.insert(marker)
}
// not showing if > 50
if (visibleMarkerSet.count > 50) {
visibleMarkerSet = Set()
break
}
}
// remove names
for markerWithName in self.iconWithNames {
if (visibleMarkerSet.contains(markerWithName) == false) {
markerWithName.removeName()
}
}
// add names
for visibleMarker in visibleMarkerSet {
visibleMarker.addName()
}
self.iconWithNames = visibleMarkerSet
}
Instead of setting marker's iconView, set marker's icon. That too initialize the image outside of for loop, as below
func displayMarkers() {
let iconImage = UIImage(named: "locationgreen")
for partner in partners {
let lat : Double = Double(partner.location?.coordinates![1] ?? 0)
let lng : Double = Double(partner.location?.coordinates![0] ?? 0)
let position = CLLocationCoordinate2D(latitude: lat, longitude: lng)
let marker = GMSMarker(position: position)
marker.title = partner.name
marker.icon = iconImage
}
}