ios google maps performselector to show infowindow - ios

I'm not sure if this is possible with Google Maps for iOS but I'm trying to refresh the open infoWindow of a marker when modal view controller is dismissed. Right now, I'm just trying to get the infoWindow to show up manually. I added a navigationItem button and sending the coordinates to the selector:
- (void) dosomething:(id)sender{
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(41.05061, 28.77244);
GMSMarker *marker = [[GMSMarker alloc]init];
marker.position = position;
[self performSelector:#selector(mapView:markerInfoWindow:) withObject:mapView_ withObject:marker];
}
- (UIView *) mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker{
NSLog(#"%f, %f", marker.position.latitude, marker.position.longitude);
InfoWindow *infoWindow = [[InfoWindow alloc]init];
NSDictionary *thisMarker = [NSDictionary new];
_thisMarker = thisMarker;
for (NSDictionary *dic in [MainMarkers sharedInstance].mainMarkers){
if ([[dic valueForKey:#"latitude"]isEqualToString:#(marker.position.latitude).stringValue] && [[dic valueForKey:#"longitude"]isEqualToString:#(marker.position.longitude).stringValue]) {
_thisMarker = dic;
}
}
NSLog(#"%#", _thisMarker);
//...infoWindow setUp
return infoWindow;
}
The logs work, I'm sending the specified coordinates but the infoWindow doesn't show up. Everything works if I tap on the marker. Is it possible to open the infoWindow this way?
UPDATE:
In the viewWillAppear method, I tried this:
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
if (_thisMarker) {
CLLocationCoordinate2D position = CLLocationCoordinate2DMake([[_thisMarker valueForKey:#"latitude"] floatValue], [[_thisMarker valueForKey:#"longitude"] floatValue]);
GMSMarker *marker = [[GMSMarker alloc]init];
marker.position = position;
mapView_.selectedMarker = (GMSMarker*)marker;
}
}
I'll add that I'm using a custom view for the infoWindow. If I add marker.map=mapView_; the infoWindow comes up but it doesn't get re-drawn, recreated based on the data (marker icon, marker name, marker details)...so I still can't get it to work.

May want to try this...
[self.mapView setSelectedMarker:marker];

If you already have a marker on the map, you can just ask the map to select it:
self.mapView.selectedMarker = (GMSMarker*)marker;
The result is the same as if the user had tapped on the marker.

Related

iOS GMaps removing old GMSMarker from map

I want to add new GMSMarker in the map and remove the old one. Previously I was using [map clear]; method and adding new marker. It was working fine. But I dont want that. I want to add new marker and remove the old marker without clearing the map each time.
My code:
if(markerMYLocation == nil)
{
markerMYLocation = [[GMSMarker alloc] init];
}
markerMYLocation.map = nil;
markerMYLocation.position = CLLocationCoordinate2DMake(latitude_Point, longitude_Point);
markerMYLocation.title = #"You";
markerMYLocation.groundAnchor = CGPointMake(0.5, 0.5);
markerMYLocation.icon = [UIImage imageNamed:#"white.png"];
markerMYLocation.map = mapViewGoog;
Question:
1) What is the correct way of removing and adding the marker?
2)I am initializing marker only in my viewDidLoad. Is that the correct way of doing this or should I initialize each time I add it?
Marker add on Map View
GMSMarker *marker = [GMSMarker markerWithPosition:[marker.getcoordinateObject MKCoordinateValue]];
marker.icon =[UIImage imageNamed:#“”];
marker.title = #“Driver Pin”
marker.map = mapView_;
[allMarkeronMap addObject:googleMapsDriverPin]; // Add maker on Array
[_mapView addSubview:mapView_];
//Make MutableArray on viewDidLoad
NSMutableArray * allMarkeronMap =[NSMutableArray alloc] init];
particualr marker or old marker remove on mapView
for (GMSMarker *pin in allMarkeronMap) {
if (pin.userData == #"Driver Pin"){
pin.map = nil;
}
}

iOS Google Maps, different custom images for Clusters and individual markers

I am using Google Maps SDK in my iOS app. I am populating the map using the clustering methods.
I have set custom images for the different clustering buckets ex. 10,20...
The individual markers however have the default (google maps red marker icon).
I would like a custom icon for clustering and a different one for single markers.
However inside the methods that render the Cluster that add markers, if you set the marker icons it changes all of the images not just singles.
How do I set different icons for singles and clusters?
this adds the items to clusterManager
id<GMUClusterItem> item =
[[POIItem alloc] initWithPosition:CLLocationCoordinate2DMake([bay.latitude doubleValue], [bay.longitude doubleValue]) name:bay.name status:bay.marker_status];
[clusterManager addItem:item];
Here I add the icons for the cluster buckets
- (id<GMUClusterIconGenerator>)iconGeneratorWithImages {
return [[GMUDefaultClusterIconGenerator alloc] initWithBuckets:#[ #10, #50, #100, #200, #1000 ]
backgroundImages:#[
[UIImage imageNamed:#"big_parking_pin_img"],
[UIImage imageNamed:#"big_parking_pin_img"],
[UIImage imageNamed:#"big_parking_pin_img"],
[UIImage imageNamed:#"big_parking_pin_img"],
[UIImage imageNamed:#"big_parking_pin_img"]
]];
}
This is where the google cluster class adds markers
- (void)renderCluster:(id<GMUCluster>)cluster animated:(BOOL)animated {
float zoom = _mapView.camera.zoom;
if ([self shouldRenderAsCluster:cluster atZoom:zoom]) {
CLLocationCoordinate2D fromPosition;
if (animated) {
id<GMUCluster> fromCluster =
[self overlappingClusterForCluster:cluster itemMap:_itemToOldClusterMap];
animated = fromCluster != nil;
fromPosition = fromCluster.position;
}
UIImage *icon = [_clusterIconGenerator iconForSize:cluster.count];
GMSMarker *marker = [self markerWithPosition:cluster.position
from:fromPosition
userData:cluster
clusterIcon:icon
animated:animated];
[_markers addObject:marker];
} else {
for (id<GMUClusterItem> item in cluster.items) {
CLLocationCoordinate2D fromPosition;
BOOL shouldAnimate = animated;
if (shouldAnimate) {
GMUWrappingDictionaryKey *key = [[GMUWrappingDictionaryKey alloc] initWithObject:item];
id<GMUCluster> fromCluster = [_itemToOldClusterMap objectForKey:key];
shouldAnimate = fromCluster != nil;
fromPosition = fromCluster.position;
}
GMSMarker *marker = [self markerWithPosition:item.position
from:fromPosition
userData:item
clusterIcon:nil
animated:shouldAnimate];
[_markers addObject:marker];
[_renderedClusterItems addObject:item];
}
}
[_renderedClusters addObject:cluster];
}
// Returns a marker at final position of |position| with attached |userData|.
// If animated is YES, animates from the closest point from |points|.
- (GMSMarker *)markerWithPosition:(CLLocationCoordinate2D)position
from:(CLLocationCoordinate2D)from
userData:(id)userData
clusterIcon:(UIImage *)clusterIcon
animated:(BOOL)animated {
CLLocationCoordinate2D initialPosition = animated ? from : position;
GMSMarker *marker = [GMSMarker markerWithPosition:initialPosition];
marker.userData = userData;
if (clusterIcon != nil) {
marker.icon = clusterIcon;
marker.groundAnchor = CGPointMake(0.5, 0.5);
}
marker.map = _mapView;
if (animated) {
[CATransaction begin];
[CATransaction setAnimationDuration:kGMUAnimationDuration];
marker.layer.latitude = position.latitude;
marker.layer.longitude = position.longitude;
[CATransaction commit];
}
return marker;
}
I had the similar problem 2 days ago and I just found the solution. Hope it will be useful for you.
For example you have a mapView and you set a delegate to it in right place:
[self.mapView setDelegate:self];
Then you need to implement the optional method from GMSMapViewDelegate protocol:
- (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position {
[self performSelector:#selector(updateMarkers) withObject:nil afterDelay:0.2];
}
I use delay 0.2 seconds, because markers wouldn't update their icons if you'll use smaller value.
The next step is implement method for updating icons:
-(void) updateMarkers {
// "mapView" property in your self.mapView has type GMSVectorMapView,
//and it is hidden, so you can't get like self.mapView.mapView
id vectorMap = [self.mapView valueForKey:#"mapView"];
// "accessibilityItems" - property that have all items in visible part of map.
NSMutableArray* GMSMarkersArray = [vectorMap mutableArrayValueForKey:#"accessibilityItems"];
// Very often you'll get object of GMSPointOfInteretUIItem class, and you don't need it =)
NSMutableArray *discardedItems = [NSMutableArray array];
for (id item in GMSMarkersArray) {
if (![item isKindOfClass:[GMSMarker class]])
[discardedItems addObject:item];
}
[GMSMarkersArray removeObjectsInArray:discardedItems];
// If marker don't have icon image, he use default red pin, but property is still have nil-value ...
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"icon = nil"];
NSArray* singleMarkers = [GMSMarkersArray filteredArrayUsingPredicate:predicate];
// ... and here you can setup any icon you want, for all singles markers in visible part of map.
for(GMSMarker* marker in singleMarkers) {
marker.icon = [UIImage imageNamed:#"yourIcon.png"];
}
}
Also if you create your own marker and add it to cluster, you can get it from userData property of GMSMarker object in last loop. And for example you have there your custom marker with icon you want, just change last loop for something like:
for(GMSMarker* marker in singleMarkers) {
YourMarkerClass* yourMaker = marker.userData;
marker.icon = yourMaker.icon;
}
Sorry for possible mistakes and ask the questions if you don't understand something =)

Is there a way to detect if a marker is present on the google map to delete it?

I'm using Google Maps SDK to write an app in Xcode and I have markers all over my map showing different locations.
I have a UIPickerView that shows markers depending on which the user selects like so:
Snippet of code:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
switch (row)
{
case 0: // Display no marker flags
{
....
}
break;
case 1: // Display vendor marker flags
{
if (isSelectedVendors == NO)
{
// Mark item as selected in picker list
isSelectedVendors = YES;
[self addVendorMarkersToMap];
}
break;
}
....
}
Snippet of method to load markers on map:
- (void)addVendorMarkersToMap
{
// Add coordinates to know where to place markers
NSArray *coords = [ [NSArray alloc] initWithObjects: ...];
// Loop through all the coordinates and mark it on the map
for (int i = 0; i < [coords count]; i = i + 2)
{
GMSMarker *marker = [ [GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake([ [coords objectAtIndex:i] floatValue], [ [coords objectAtIndex: (i + 1)] floatValue]);
marker.appearAnimation = kGMSMarkerAnimationPop;
marker.icon = [UIImage imageNamed:#"vendors.png"];
marker.map = mapView;
}
}
Google Map's documentation doesn't explain how to detect markers on the map.
Since I'm using a UIPickerView to display certain markers on the map, how do I detect markers on the map to delete them and only show the markers the user selects from the UIPickerView?
The only thing I know to do is to use [mapView clear] but then that would clear everything on the map, even the overlay that I have over the map.

Google maps iOS sdk get tapped overlay coordinates

i'm working with Google maps iOS sdk.
i want to get the coordinates of the touched point when user taps an overlay.
there is this delegate method:
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate
but it's not called when you tap an overlay or a marker.
can i call it programmatically (but coordinate parameter is missing-that's what i want..)?
or get location from this:
- (void) mapView: (GMSMapView *) mapView didTapOverlay: (GMSOverlay *) overlay
any suggestion's precious!
thanks!
UPDATE 6/2/15
Just staple a UITapGestureRecognizer onto the map and then extract the coordinate from the touch point. Your didTapAtCoordinate and didTapAtOverlay will continue to fire as before.
UITapGestureRecognizer *touchTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTouchTap:)];
[self.view addGestureRecognizer:touchTap];
-(void)tapTouchTap:(UITapGestureRecognizer*)touchGesture
{
CGPoint point = [touchGesture locationInView:self.view];
CLLocationCoordinate2D coord = [self.mapView.projection coordinateForPoint:point];
NSLog(#"%f %f", coord.latitude, coord.longitude);
}
ORIGINAL POST
You are likely missing two snippets of code.
Adopt the GMSMapViewDelegate in your header file:
#interface Map : UIViewController <GMSMapViewDelegate>
You also need to set the delegate in your viewDidLoad:
self.mapView.delegate = self;
Now this should fire for you:
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate
{
NSLog(#"You tapped at %f,%f", coordinate.latitude, coordinate.longitude);
}
If you just want to get the position of the marker, there is a position property
CLLocationCoordinate2D coord = marker.position;
When this delegate method gets called
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate
its for screen taps that have no markers or overlays from my expierience.
GMSOverlay is a bit different because its a super class to a GMSMarker. You just need to subclass GMSOverlay for your custom overlays and add a position property. When you create the overlay, say in didTapAtCoordinate, you can assign the position (GPS coord) in there.
You could set the circle not tappable (default behaviour) and catch all the clicks on the map with the didTapAtCoordinate delegate.
Then when this event is triggered you could loop over all your circles to check if the user tapped inside one of the circles or outside.
self.mapview.settings.consumesGesturesInView = NO;
Add this line in viewdidload or after allocating.
And then implement this delegate method.
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate
{
NSLog(#"%g",coordinate);
}
- (void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSOverlay *)overlay
{
GMSCircle *circle=(GMSCircle *)overlay;
CLLocationCoordinate2D touchCoOrdinate= circle.position;
NSLog(#"%g",touchCoOrdinate);
}
So you can't get the didTapAtCoordinateMethod to fire for an overlay tap. However I did find a slightly dirty workaround.
Using an overlay to draw polylines, we need a way to recognize where a polyline was tapped. So when drawing polylines we can build them like this.
//draw line
GMSPolyline *polyline = [GMSPolyline polylineWithPath:path];
polyline.strokeColor = [UIColor purpleColor];
polyline.tappable = TRUE;
polyline.map = self.googleMapView;
polyline.title = routestring;
Where routestring is a built string from
routestring = [NSString stringWithFormat:#"%#/%#/%#",lat,lng,[annnotationobject objectForKey:#"linkId"]];
And lat and lng are string values of our coordinates. The last part is an ID for the polyline.
The routestring is storing the coordinates and an ID separated by '/' so that we can use component path of string to look them up later. This is assigned to the polylines title.
Now when the overlay is tapped:
-(void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSOverlay *)overlay{
NSString *path = overlay.title;
//Finding componentpaths of string
NSArray *pathparts = [path pathComponents];
NSString *lat = [pathparts objectAtIndex:0];
NSString *lng = [pathparts objectAtIndex:1];
NSString *linkID = [pathparts objectAtIndex:2];
//Here we are building a marker to place near the users tap location on the polyline.
GMSMarker *marker = [GMSMarker markerWithPosition:CLLocationCoordinate2DMake([lat doubleValue],[lng doubleValue])];
marker.title = overlay.title;
marker.snippet = #"ROUTE DATA";
marker.map = self.googleMapView;
//This will popup a marker window
[self.googleMapView setSelectedMarker:marker];
}
We can use component paths of the string we built(separated by "/")to get the latitude and longitude coordinates from the polyline. Then assign them a marker to popup information on the overlay item.
You can subclass UITapGestureRecognizer and override its touchesEnded to retrieve the touch point, than retrieve the coordinate with GMSMapView's coordinateForPoint.
Subclass UITapGestureRecognizer and add it to your mapView:
self.touchTap = [[TouchGestureRecognizer alloc] initWithTarget:self action:#selector(tapTouchTap)];
self.touchTap.mapView = self.mapView;
[self.view addGestureRecognizer:self.touchTap];
TouchDownGestureRecognizer.h:
#import <UIKit/UIKit.h>
#interface TouchGestureRecognizer : UITapGestureRecognizer
#property GMSMapView *mapView;
#end
TouchDownGestureRecognizer.m:
#import "TouchGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>
#implementation TouchGestureRecognizer
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
UITouch *touch = touches.allObjects[0];
CGPoint point = [touch locationInView:self.mapView];
CLLocationCoordinate2D coord = [self.mapView.projection coordinateForPoint:point];
NSLog(#"%f %f", coord.latitude, coord.longitude);
}
#end

add Marker on the Map using Mappy SDK IOS

i'm developing and iphone app and i'm working with Mappy SDK IOS.
i arrived to display the map and show my current location. but i have a problem with adding some markers on my map.
i have an NSArray that contains some objects with longitude and latitude properties.
my code to display the markers is :
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//initialisation mot de passe + user
[MPInit initialisation:MAPPY_API_KEY];
[RMMapView class];
//show user location
self.mapView.showsUserLocation = NO;
self.mapView.showPoi = YES;
//set delegate
self.mapView.delegate = self;
MPMarkerManager *markerManager = [self.mapView markerManager];
MPMarkerCategory * category = [markerManager getCategory:#"storeLocations"];
//remove old elements
[category.dataSource removeAllElements];
//add markers on map
for(int i=0; i<self.arrayStores.count; i++) {
NSLog(#"add store %d on the map", i);
NSDictionary* currentStore = [self.arrayStores objectAtIndex:i];
float latitude = [[currentStore objectForKey:#"latitude"] floatValue];
float longitude = [[currentStore objectForKey:#"longitude"] floatValue];
CLLocationCoordinate2D locationStore = CLLocationCoordinate2DMake(latitude, longitude);
//create a new POI object with location
MPPoi * poi = [[MPPoi alloc] initWithUId:[currentStore objectForKey:#"title"] withLocation:locationStore];
[category.dataSource addElement:poi];
self.mapView.centerCoordinate = locationStore;
[poi release];
}
//category settings
category.markerColor = [UIColor greenColor];
//[category setOptimalZoom:YES];//set the zoom to be optimal : show all poi in the category
[category setHideLabelOnTheFirstShow:NO];
[category setAnimateAtFirstShow:YES];
}
and here is the log displayed on the console:
2012-06-14 17:01:18.359 Koutoubia[609:607] MappyKit version:1.40
2012-06-14 17:01:18.672 Koutoubia[609:607] add store 0 on the map
i'm i doing something wrong ?? because markers aren't displayed
the doc for adding markers on the documentation is :
//add a marker on map
MPMarkerManager *markerManager = [viewController.mapView markerManager];
MPMarkerCategory * category = [markerManager getCategory:HMP_LOC_CATEGORY];
//remove old elements
[category.dataSource removeAllElements];
//create a new POI object with location
MPPoi * poi = [[MPPoi alloc] initWithUId:locationData.address withLocation:findLocation];
[category.dataSource addElement:poi];
[poi release];
the link of the documentation is here
any ideas ?? thanks in advance
I've founded the solution ,
the problem is that i've forgot to initialize the MPMarkerCategory and add it to the markerManager on the viewDidLoad method :
//Marker initialization
MPMarkerManager *markerManager = [self.mapView markerManager];
//add a new category with green default color
[markerManager addCategory:STORE_LOC_CATEGORY withColor:[UIColor greenColor]];

Resources