SKMaps iOS: Pin disappears when panning the Map - ios

With the new Version (2.1.0) I get a problem. The Annotation disappears when scrolling the map.
In the demo project it works fine. Also adding the frameworks again doesn't help.
- (void)viewDidLoad {
[super viewDidLoad];
placeDetail = [[PlaceDetailViewController alloc] init];
latitude = [placeDetail Latitude];
longitude = [placeDetail Longitude];
self.placeMapView = [[SKMapView alloc] init];
self.placeMapView.frame = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame));
self.placeMapView.delegate = self;
self.placeMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.placeMapView.settings.poiDisplayingOption = SKPOIDisplayingOptionNone;
[self.view addSubview:self.placeMapView];
//add a circle overlay
for(int i=0;i<latitude.count;i++)
{
//set the map region
SKCoordinateRegion region;
region.center = CLLocationCoordinate2DMake([latitude[i] floatValue], [longitude[i] floatValue]);
region.zoomLevel = 17;
self.placeMapView.visibleRegion = region;
SKAnnotation *mapAnnotation = [SKAnnotation annotation];
mapAnnotation.identifier = i;
mapAnnotation.minZoomLevel = 5;
mapAnnotation.annotationType = SKAnnotationTypeRed;
mapAnnotation.location = CLLocationCoordinate2DMake([latitude[i] floatValue], [longitude[i] floatValue]);
[self.placeMapView addAnnotation:mapAnnotation];
}
}
Annoation creation
-(void)mapView:(SKMapView *)mapView didSelectAnnotation:(SKAnnotation *)annotation {
self.placeMapView.calloutView.titleLabel.text= placeDetail.Name;
self.placeMapView.calloutView.titleLabel.font = [UIFont fontWithName:#"PTSans-Narrow" size:15];
self.placeMapView.calloutView.subtitleLabel.text = #"";
[self.placeMapView showCalloutForAnnotation:annotation withOffset:CGPointMake(0, 42) animated:YES];
[self.placeMapView.calloutView.rightButton addTarget:self action:#selector(backToDetailView) forControlEvents:UIControlEventTouchUpInside];
}
I would appreciate your help.
EDIT: I think I found the problem that causes this beahvior. In my app I have two kind of maps. One Mini Map and one large Map. But in two different views.
When I deactivate the Mini Map it works. SO I think it has to do with the loading of the SKMap framework. Currently the mini map function is called in view did load method.
So you know what to do here?

It is a bug in the 2.1 and 2.2 versions of the SDK - it will be fixed in 2.3 (eta November 2014).
For 2.1/2.2 there is a workaround: having different id's for the annotations on the minimap and the big map. For example you have N annotations on the minimap with ids 0..N-1, then the big map would have annotations with ids from N onward. So for M annotations on the big map you would have annotations with ids from N..M-1.

Related

iOS Google Maps: Coordinates Mismatch

One of our application's feature is to plot a location on the map, we will save it in our server and show it on the main screen of the application. We are using Google Maps and GMSMarker with draggable property set to YES. But there is a difference between the marked location and the coordinate obtained.
Code:
NSDictionary *signDict = self.imgLocationsArray[_currentIndex];
_toSaveLat = [signDict[TAG_SIGN_LAT] floatValue];
_toSaveLon = [signDict[TAG_SIGN_LONG] floatValue];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:_toSaveLat longitude:_toSaveLon zoom:GOOGLE_MAPS_DEFAULT_ZOOM_LEVEL];
self.dragDropMap = [GMSMapView mapWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) camera:camera];
[self.dragDropMap setMapType:kGMSTypeNormal];
[self.dragDropMap setDelegate:self];
self.dragDropMap.myLocationEnabled = YES;
[self.view addSubview:self.dragDropMap];
if (draggingMarker) {
draggingMarker.map = nil;
draggingMarker = nil;
}
draggingMarker = [[GMSMarker alloc] init];
draggingMarker.icon = [GMSMarker markerImageWithColor:[UIColor plumColor]];//[UIImage imageNamed:#"MoveablePin"];
draggingMarker.position = CLLocationCoordinate2DMake(_toSaveLat, _toSaveLon);
draggingMarker.tappable = NO;
draggingMarker.draggable = YES;
draggingMarker.map = self.dragDropMap;
-(void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker{
NSLog(#"marker dragged to location: %f,%f", marker.position.latitude, marker.position.longitude);
_toSaveLat = marker.position.latitude;
_toSaveLon = marker.position.longitude;
}
Am I missing something in the code or anything else? Please suggest a solution or workaround to get this fixed. Thanks!
Testing Environment
xCode - 7.0
Google Maps SDK version - 1.10.3 (Using pod)
Device - iPhone 5S, iPhone 6plus
iOS - 9.0.2

MapBox. layerForAnnotation not being called. Drawing shape

I am trying to draw a path for the user from point A to point B with given coordinates.
LayerForAnnotation isn't being called after I add the annotation. I am new to using MapBox SDK and don't really know what I'm doing wrong. I looked for instructions on adding Shapes on the MapBox documentation. I tried changing to RMPointAnnotation but did not work and isn't supposed to according to this: Issue GitHub RMAnnotation.
I have checked if there is any info about the implementation of this delegate but haven't found a lot on the MapBox documentation page. I downloaded the example project that illustrates annotations from here: Weekend Picks sample.
This is the code I am using:
- (void) makeRoutingAnnotations
{
// Translate updated path with new coordinates.
NSInteger numberOfSteps = _path.count;
NSMutableArray *coordinates = [[NSMutableArray alloc] init];
for (NSInteger index = 0; index < numberOfSteps; ++index) {
CLLocation *location = [_path objectAtIndex:index];
[coordinates addObject:location];
}
RMAnnotation *startAnnotation = [[RMAnnotation alloc] initWithMapView:mapView coordinate:((CLLocation *)[coordinates objectAtIndex:0]).coordinate andTitle:#"Start"];
startAnnotation.userInfo = coordinates;
[startAnnotation setBoundingBoxFromLocations:coordinates];
[mapView addAnnotation:startAnnotation];
}
- (RMMapLayer *)mapView:(RMMapView *)mView layerForAnnotation:(RMAnnotation *)annotation
{
if (annotation.isUserLocationAnnotation)
return nil;
RMShape *shape = [[RMShape alloc] initWithView:mView];
// set line color and width
shape.lineColor = [UIColor colorWithRed:0.224 green:0.671 blue:0.780 alpha:1.000];
shape.lineWidth = 8.0;
for (CLLocation *location in (NSArray *)annotation.userInfo)
[shape addLineToCoordinate:location.coordinate];
return shape;
}
What could I be missing? I made a droppoint on the layerForAnnotation method but it isn't being called.
I found the problem I hadn't properly implemented the RMMapViewDelegate. Since it wasn't properly implemented it wasn't called.
Suffices to add it on the header file and assign it in code.
mapView.delegate = self;

How to add clicked annotations on mapbox using offline mbtiles files

I have already managed to use interactive offline mbtiles (created on TileMill) in order to:
Load more than 1000 points fast
Make them understand when user is clicking each point and show a popup with the name of each point
But I can't make the bubble with the name clickable again.
I use the following code to generate the layer for the annotation of each point
- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation{
RMMarker *marker = [[RMMarker alloc] initWithMapboxMarkerImage:#"embassy"];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 32)];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image = annotation.userInfo;
marker.leftCalloutAccessoryView = imageView;
marker.canShowCallout = YES;
return marker;
}
and this is how I get the teaser and build my annotation from the mbtiles file:
- (void)singleTapOnMap:(RMMapView *)mapView at:(CGPoint)point{
[mapView removeAllAnnotations];
RMMBTilesSource *source = (RMMBTilesSource *)mapView.tileSource;
if ([source conformsToProtocol:#protocol(RMInteractiveSource)] && [source supportsInteractivity])
{
NSString *formattedOutput = [source formattedOutputOfType:RMInteractiveSourceOutputTypeTeaser
forPoint:point
inMapView:mapView];
if (formattedOutput && [formattedOutput length])
{
// parse the country name out of the content
//
NSUInteger startOfCountryName = [formattedOutput rangeOfString:#"<strong>"].location + [#"<strong>" length];
NSUInteger endOfCountryName = [formattedOutput rangeOfString:#"</strong>"].location;
NSString *countryName = [formattedOutput substringWithRange:NSMakeRange(startOfCountryName, endOfCountryName - startOfCountryName)];
// parse the flag image out of the content
//
NSUInteger startOfFlagImage = [formattedOutput rangeOfString:#"base64,"].location + [#"base64," length];
NSUInteger endOfFlagImage = [formattedOutput rangeOfString:#"\" style"].location;
UIImage *flagImage = [UIImage imageWithData:[NSData dataFromBase64String:[formattedOutput substringWithRange:NSMakeRange(startOfFlagImage, endOfFlagImage)]]];
RMAnnotation *annotation = [RMAnnotation annotationWithMapView:mapView coordinate:[mapView pixelToCoordinate:point] andTitle:countryName];
annotation.userInfo = flagImage;
[mapView addAnnotation:annotation];
[mapView selectAnnotation:annotation animated:YES];
}
}
}
UPDATED
I figured out how to do that by using a leftCalloutAccessoryView on the marker (I added the following at the end of layerForAnnotation method :
marker.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
and used the following delegate method to track the event:
-(void)tapOnCalloutAccessoryControl:(UIControl *)control forAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map{
NSLog(#"I will now pass to the next screen ! YEAH! %#",annotation.title);
}
The problem now is that I want to get rid off the left calloutAccesoryView. Any suggestions?
None of what you have here about the map is needed. What you really want is the callout (which is of type SMCalloutView, a dependent project to the Mapbox SDK that you are using) to have its clicks registered.
Check out this issue for more details:
https://github.com/mapbox/mapbox-ios-sdk/issues/422

Zoom to random annotation and show bubble when map view loads

I am trying to zoom to a random annotation AND have the bubble open automatically as well.
I am pinning my annotations in the viewDidLoad as follows:
...arrays...
for (int i=0; i<22; i++){
MKPointAnnotation *annot = [[MKPointAnnotation alloc] init];
annot.title = [wineryName objectAtIndex:i];
annot.subtitle = [wineryAddress objectAtIndex:i];
annot.coordinate = CLLocationCoordinate2DMake([[lat objectAtIndex:i]doubleValue], [[lon objectAtIndex:i]doubleValue]);
[mapView setCenterCoordinate:annot.coordinate animated:YES];
[mapView addAnnotation:annot];
then I am styling the bubble as follows:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
//dequeue an existing pin view first
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView* pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop=YES;
pinView.canShowCallout=YES;
pinView.pinColor=MKPinAnnotationColorRed;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 35, 35);
button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[button setImage:[UIImage imageNamed:#"RightArrow.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = button;
...arrays...
for (int i = 0; i < 22; i++) {
if ([wineryTitle[i] isEqualToString:[annotation title]]) {
UIImageView *profileIconView = [[UIImageView alloc] init];
profileIconView.frame = CGRectMake(0, 0, 40, 33);
profileIconView.image = [UIImage imageNamed:wineryImage[i]];
pinView.leftCalloutAccessoryView = profileIconView;
[profileIconView release];
break;
}
}
return pinView;
}
then I am trying to zoom to a random location as follows:
- (void)zoomToUserLocation:(MKUserLocation *)userLocation
{
if (!userLocation)
return;
MKCoordinateRegion region;
//zoom to random pin when page loads
int randomNumber = rand() % 22;
switch (randomNumber) {
case 1:
region.center = CLLocationCoordinate2DMake(34.642109, -120.440292);
[self.mapView selectAnnotation:[self.mapView.annotations objectAtIndex:0] animated:TRUE];
break;
case 2:
region.center = CLLocationCoordinate2DMake(34.667408, -120.334781);
[self.mapView selectAnnotation:[self.mapView.annotations objectAtIndex:1] animated:TRUE];
break;
case 3:
...etc
}
region.span = MKCoordinateSpanMake(5.0, 5.0);
region = [self.mapView regionThatFits:region];
[self.mapView setRegion:region animated:YES];
}
ALL OF THIS WORKS< EXCEPT: In the zoomToUserLocation method, the map is zooming to one location and then showing the bubble of a different location. It seems like the random operator is randomly selecting a location and a bubble separately. Does anyone know how to fix this so that the bubble automatically appears at the same location that is randomly selected?
The code in the zoomToUserLocation method is making the wrong assumption that the map view's annotations array only contains the annotations you explicitly added and (more importantly) that the annotations array will be in the same order that you added the annotations in.
Both of those assumptions are unsafe to make.
For some more discussion, see MKMapView annotations changing/losing order?.
Your app is apparently adding 22 annotations but:
If showsUserLocation is YES, then the map view's annotations array will contain 23 annotations (your 22 and the user location that the map adds itself).
There is no guarantee that the annotation at index N of the map's annotations array will be the same annotation that is at index N in your winery array.
For your purpose of simply zooming to a random location, it is not really necessary to establish a link between the map's annotations array and your own array(s).
Instead, the coordinates to center on can be retrieved from the randomly chosen annotation from the annotations array itself.
For example:
MKCoordinateRegion region;
//make list of annotations excluding the user location
NSMutableArray *myAnnotations = [NSMutableArray arrayWithCapacity:10];
for (id<MKAnnotation> ann in self.mapView.annotations)
{
if (! ([ann isKindOfClass:[MKUserLocation class]]))
[myAnnotations addObject:ann];
}
int numOfAnnotations = myAnnotations.count;
//if no annotations to choose from, do nothing
if (numOfAnnotations == 0)
return;
int randomNumber = rand() % numOfAnnotations;
//suggest using arc4random instead of rand
//see https://stackoverflow.com/questions/160890/generating-random-numbers-in-objective-c
id<MKAnnotation> randomAnnotation = [myAnnotations objectAtIndex:randomNumber];
region.center = randomAnnotation.coordinate;
[self.mapView selectAnnotation:randomAnnotation animated:YES];
region.span = ... //rest of the code as-is
//however, calling regionThatFits is unnecessary
There are numerous other unrelated improvements that could be made to the code but those will have to be the topic of separate questions. Here are a couple of them however...
One major improvement I can suggest is to create a custom annotation class (called Winery perhaps) which consolidates all the data of a winery into a single object rather than using separate arrays for the name, address, latitude, longitude, image, etc.
This will make development and future changes much easier to manage.
The second major improvement is to remove the inefficient loop in the viewForAnnotation delegate method which searches for the winery name in order to set the left accessory view's image. This search loop is executed every time the annotation view is needed. With just 22 annotations, you may not notice a performance issue but it's unnecessary work. If the first improvement is done, the search loop can be eliminated since all the annotation's properties will already be in the annotation object.
See Optimizing Code for MKMapView - Large Number of Annotations for some idea of the above.

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