I want to hide/show annotations on a map based on filters.
My approach is currently to return nil or a RMMapLayer in
- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation
It works quite as expected but if the filters are changed when the map is visible, the changes are not reflected to the map if it is not paned or zoomed (annotations that go off screen and back in screen are correctly affected -ie hidden/shown- by the filters, but annotations not leaving the screen bounds are not affected).
Is there a way to achieve this without removing and replacing all annotations on the map each time the filters are modified ?
Thanks.
You may want to look into this pull request which was not incorporated but helps with this functionality: https://github.com/mapbox/mapbox-ios-sdk/pull/113
Related
I am using map box sdk for my application to get customized map. I able to change color of land, sea, street,etc. But I also have to make callout customized as show in image below. The small rectangle is closed callout the big rectangle is when call out pop is up.
The documentation contains an example of how to do this.
You have to implement the following delegate method and return your custom marker.
- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation
I would like to know how I can make sure that a callout bubble can't get deselected on a MKMapView.
Whenever I press on the map (background), this view:
Turns to:
Which I do not want to allow. Yet I do want to keep the callOutButton support.
You could just programmatically select your annotation whenever annotations get deselected (using the corresponding delegate method). If you don't animate this selection then it looks as if the annotation never got deselected in the first place.
Example:
// MKMapView Delegate
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
// Replace "myAnnotation" with whichever annotation you need to remain selected
[mapView selectAnnotation:self.myAnnotation animated:NO];
}
I tried this in a test project and it works fine (it doesn't flicker or anything). It's not exactly disabling deselection but the resulting effect is the same, so it might be a good workaround.
I've got a performance problem regarding adding annotations to maps in iOS (using the standard mapkit methods - hence using Apple maps). I'm trying to add a large number of annotations (10000+) in bulk, using the (void)addAnnotations:(NSArray *)annotations method. The annotation objects are nothing special - a very basic class that implements MKAnnotation with only the constructor defined as follows:
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d {
if(self = [super init]) {
title = ttl;
coordinate = c2d;
}
return self;
}
In order to test, I've created a basic app that simply adds the annotations to a basic map view on load, and it takes around 6-7 seconds on an iPad 2. Very acceptable performance. However, things get complicated when I embed the same basic map view in my own application. It's the exact same logic, but when I do it in my app, it takes around 50 seconds to load all the annotations.
My app has a bunch of views within each other. To pinpoint the problem, I've started embedding the map view starting from the lowest level, until I reach the top level. I've done profiling in each step to see if it helps the performance, but I don't see any results - it's still around 50 seconds. Right now, my app basically just loads and adds the annotations to the top and only level map view, ideally the same as the standalone app, but for whatever reason, I still see the annotation rendering taking around 50 seconds. The only reasonable explanation I have is in regards to some of the app settings I have that somehow interferes with the map performance. I've done a bunch of reading to come up with a solution to no avail.
Anyone have any ideas about what might be the problem here? Thanks!
There is no actual "problem". I mean, you have more than 10000 allocations, draws and renderings that are actually having impact on the performance of the application.
My suggestion is to intercept the user navigation on the map. Use something like [mapView visibleMapRect] to get the visible portion of the map on the screen. Get the coordinates of the rect (maybe a little bit bigger so that cannot be noticed by the user when moving the map) and load only the annotations within that rect.
As the user moves, you only have to load the annotations that are within the new rect MINUS the annotations that were already loaded in the previous rect. I guess you can also remove the annotation when they go out of the screen.
This resembles a little bit what Apple suggests to do when dealing with scrolling views. I remember the application in which the user would have to load the content of the previous and next section of the scrollview (and to release the content of the previous-1 view) so to have a slow memory consumption and still maintaining a good user experience.
Try to think about what the user is looking at, try to show only the annotations that matter that portion (or region as they are called in the MKMapView jargon) and I think your app responsiveness will just improve right away.
I'm encountering a mystery issue when selecting a pin in the mapview iOS6
BTW, it works correctly in iOS 5, i'm not sure what they changed in the map of iOS 6 that produce this issue.
NOTE that when I click on the map, the callout directly go over the pins and shows correctly
any help/clue would be appreciated,
Thanks in advance
the answer might vary a bit depending on how you're implementing your custom callout bubble. This was/is the solution I'm using: Customize the MKAnnotationView callout and I ran into the exact same problem.
Basically, everytime the callout is going to show, I had to bring the subview to the front.
In this case, my custom callout bubble is a class called 'BaseCalloutView' which contains a UIView as its ContentView property (as you can see in the UML diagram at the link above). When the annotation is selected, it triggers the 'animateIn' function of the BaseCalloutView, into which I added:
[self.superview bringSubviewToFront:self];
As I mentioned, your mileage may vary depending on how you're implementing the custom callout bubble. I can provide you with the full code if needed - but to be honest 90% of my code is from the link above.
This solution didn't work for me, however the one did:
Custom Annotation View do not work on iOS6
Sorry not sure how to link answers properly.
In IOS 5 and IOS 6 , I try this and it's ok
the pin never overlap CalloutView.
I use custom calloutview , in file Base calloutView I add this :
- (void)didMoveToSuperview {
[super didMoveToSuperview];
[self.superview bringSubviewToFront:self];
}
I am using same code base, got same problem. [self.superview bringSubviewToFront:self]; doesn't work for me, not matter where did I put it. [annimateIn] or [didMoveToSuperView] or [layoutIfNeeded]
Because this problem went away by finger moving the map a little bit, so I found it is very easy to simulate this effect by put code in - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view. The offset is very small, no visual movement can be noticed at all.
CLLocationCoordinate2D newCenterCoordinate = {self.mapView.region.center.latitude + 0.0000001,
self.mapView.region.center.longitude + 0.0000001};
[self.mapView setCenterCoordinate:newCenterCoordinate animated:NO];
Would really love an answer to this question https://devforums.apple.com/message/723468. I can't post the details because its about iOS 6 and is Confidential per Apple.
Please post the answers/comments to the Apple Dev forums post and let me know about it here.
EDIT: Since iOS6 is officially released:
In my pre-ios6 code I'm doing this to rotate the map when the user location moves:
//this is in my MKMapViewDelegate
-(void) rotateMap:(MKMapView *)mapViewTmp forLocation:(MKUserLocation *) userLocation {
...
//calculate needed rotation
...
[mapViewTmp setTransform:CGAffineTransformMakeRotation(lastRotation)]; //rotate the MKMapView
for (id<MKAnnotation> annotation in mapViewTmp.annotations) {
MKAnnotationView* annotationView =[mapViewTmp viewForAnnotation:annotation];
[annotationView setTransform:CGAffineTransformMakeRotation(-lastRotation)]; //counter rotate the Annotation Views
[annotationView setNeedsDisplay]; //ios6
}
}
And this worked fine (1000s of users).
In ios6 however (I updated Xcode/sdk on 9/4/2012), the annotation views do not maintain this rotation (for example if map is panned). They flip back to their non rotated state (which, since my map is rotated means they show text at an angle instead of horizontal).
The code does temporarily rotate the annotations so their text appears horizontal, but if map is panned (and their seem to be other causes as well) then the annotations flip to their non-rotated state and my annotation text appears at an angle relative to the rotated map.
What is the correct way to rotate an MKAnnotationView so that it stays rotated in IOS6? What has changed in MKMapView that caused the change?
The fix for this is to do the following in the viewForAnnotation method:
// iOS6 BUG WORKAROUND !!!!!!!
if (is6orMore) {
[annotationView setTransform:CGAffineTransformMakeRotation(.001)]; //any small positive rotation
}
This was posted as a comment by me in the original question and then posted by cristis as an answer (referencing my comment), but I'm posting and accepting my own answer since it was me that came up with it. Did that make sense?
This was posted as a comment, I'm re-posting it as an answer so anyone can see it easily (and waste less time trying to figure it out).
And the fix is===>in viewForAnnotation method:
// iOS6 BUG WORKAROUND !!!!!!!
if (is6orMore) {
[annotationView setTransform:CGAffineTransformMakeRotation(.001)];
}
I saw the same thing. Here's the fix:
Set YOUR transform on the child of the MKAnnotationView, so in pseudo-ish code:
view.child.transform = CGAffineTransformMakeRotation(0.3);
Let them have control of the annotation view and take control of your view subtree. Transforms concatenate and you'll inherit whatever they do in position. Works for me on iOS 6.