User location image pin disappears most of time - iphone

i Am using following code
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([[annotation title] isEqualToString:#"Current Location"] )
{
MKAnnotationView *anView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentPin"];
anView.image = [UIImage imageNamed:#"pin_green.png"];
anView.canShowCallout = true;
anView.enabled = true;
return anView;
}
The issue is, it randomly disappears and appears again. Giving a very bad user experience. Any way to fix this?

There are several suspect things about this code:
You're not using dequeue, as someone has pointed out. In particular, the problem here is that you are making a new view every single time, rather than checking to see whether a new view needs making.
You are forgetting the key step, namely, to associate the view with the annotation.
Here is the canonical structure of a simple viewForAnnotation: implementation where we supply our own view:
- (MKAnnotationView *)mapView:(MKMapView *)mapView
viewForAnnotation:(id <MKAnnotation>)annotation {
MKAnnotationView* v = nil;
if ([annotation.title isEqualToString:#"Current Location"]) {
static NSString* ident = #"greenPin";
v = [mapView dequeueReusableAnnotationViewWithIdentifier:ident];
if (v == nil) {
v = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:ident];
v.image = [UIImage imageNamed:#"pin_green.png"];
v.canShowCallout = YES;
}
v.annotation = annotation;
}
return v;
}
Since that code works for me, I'd suggest you start with it and tweak it as necessary.
By the way, you do NOT need this method just to get a green pin! You do know that, right? iOS will give you a green pin (MKPinAnnotationColorGreen).

You should use MKMapView's dequeueReusableAnnotationViewWithIdentifier: and see if you get a view back before creating a new one with initWithAnnotation:reuseIdentifier::
MKAnnotationView *anView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"currentPin"];
if (!anView) {
anView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentPin"];
anView.image = [UIImage imageNamed:#"pin_green.png"];
anView.canShowCallout = true;
anView.enabled = true;
}
return anView;
That said, I'm not entirely sure this is the cause of your problem.

Related

ios6 MKMapView deselection bug

I observed a strange behavior with the map in iOS 6.
Here is a code which adds a single annotation, absolutely nothing else in the project:
- (void)viewDidLoad
{
[super viewDidLoad];
MKPointAnnotation * p = [[MKPointAnnotation alloc] init];
p.coordinate = CLLocationCoordinate2DMake(10, 10);
p.title = #" test test";
[self.mapView addAnnotation:p];
self.mapView.centerCoordinate = p.coordinate;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id < MKAnnotation >)annotation
{
MKPinAnnotationView * p = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"wassup" ];
p.canShowCallout = YES;
p.pinColor = MKPinAnnotationColorGreen;
return p;
}
When it is selected and I move (pan) the map small distances like 0.5-1 cm, on iOS6 the annotation gets deselected. On earlier versions works as expected and remains selected.
Is it a bug ? Is there any workaround for this ?
Thanks !
Apple maps are full of bugs.. LOL you noticed that too..
Its a feature of iOS 6 sometime can irritate the the user.. :)
in annotaionView method use:
// iOS6 BUG WORKAROUND !!!!!!!
if (is6orMore) {
[annotationView setTransform:CGAffineTransformMakeRotation(.001)]; //any small positive rotation
}
Also see the link
If you want to not deselect an annotation view, you should subclass MKAnnotationView and override the setSelected:animated: method and stop the annotation view from being deselected.

App crashing when I add overlay to mkmapview

I am trying to add annotations and overlays to a mapview but it crashes randomly. It is an EXC_BAD_ACCESS error, but zombies doesn't tell me anything. It says it is crashing on CG::Path::apply_transform(CGAffineTransform const&). I have looked everywhere for why this is happening but can't pinpoint it.
I am creating the mapview in ib and have the delegates and everything set up right. It will work sometimes and then crash randomly.
I am using a gesture recognizer to add the annotations and overlay
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.mapView addGestureRecognizer:doubleTap];
and
- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateRecognized){
CGPoint touchPoint = [gestureRecognizer locationInView:self.mapView];
CLLocationCoordinate2D touchMapCoordinate =
[self.mapView convertPoint:touchPoint toCoordinateFromView:self.mapView];
//add pin where user touched down...
MKPointAnnotation *pa = [[MKPointAnnotation alloc] init];
pa.coordinate = touchMapCoordinate;
//[pa setTitle:#"title"];
[mapView addAnnotation:pa];
MKCircle* circle=[MKCircle circleWithCenterCoordinate:touchMapCoordinate radius:500];
[mapView addOverlay:circle];
}
}
And the views for each:
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay
{
if ([overlay isKindOfClass:[MKCircle class]]) {
MKCircleView* circleView = [[MKCircleView alloc] initWithOverlay:overlay];
circleView.strokeColor = [UIColor redColor];
circleView.lineWidth = 1.0;
circleView.fillColor = [UIColor blackColor];
circleView.alpha=.5;
return circleView;
}
else
return nil;
}
- (MKAnnotationView *)mapView:(MKMapView *)localmapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if (![annotation isKindOfClass:[MKUserLocation class]]) {
static NSString *AnnotationIdentifier = #"Annotation";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)[localmapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.animatesDrop = YES;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
Is there a better way to add annotations/overlays to maps with user interaction? Am I doing something wrong in this code? It appears to draw most of the circle but then crashes... Is there some special trick to mapviews?
I've been getting the exact same error:
CG::Path::apply_transform(CGAffineTransform const&) will hit a test instruction and give me an EXC_BAD_ACCESS
This specifically occurs when using a double click on the map to zoom in on an MKCircle.
I can't say this definitively, but to the best of my knowledge this problem only occurs on the simulator when you use a double click to zoom, I've never been able to cause the error from an actual device, or by using option+click to zoom on the simulator.
So at this point I've filed this under "simulator bug" and left it at that.
If you do discover anything to the contrary, please let me know because it really bothers me not explicitly knowing whether or not this is a bug existing in my app that I just can't properly reproduce.
edit:
This was flagged initially as "not an answer" so I'll provide a little bit more information supporting my conjecture.
Basically in both of our scenarios a gesture is firing the re-rendering of the MKCircleView, what I strongly suspect is that since the simulator is able to generate some kind of gesture which can't be created from a user on the actual device, there is a failed expectation somewhere down the chain while that gesture gets handled.
I am not sure where your EXC_BAD_ACCESS problems is. But you have a big problem with leaking memory. You have to releas object that you create with init. In the above code you create objects and never release them. That will not throw EXC_BAD_ACCESS but it will consume your memory.
Release the following object :
MKPointAnnotation *pa = [[MKPointAnnotation alloc] init];
MKCircleView* circleView = [[MKCircleView alloc] initWithOverlay:overlay];

viewForAnnotation problem-Images are not placing properly on google map in iPhone

In my Application I have to show the google map along with pin images. I have to place two images according to the condition(branch,atm).In viewForAnnotation method I am doing code for the same,in NSLog I am getting the correct output but annotation images aren't placing properly.
Images are placing inconsistently.Here is my code.
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{
NSString* identifier = #"Pin";
MKAnnotationView* annView = [searchMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
AddressAnnotation *delegate = annotation;
Location *newLoc = [searchData objectAtIndex:countATMandBranch];
if (annView == nil) {
annView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"cell"]autorelease];
annView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
if(newLoc.isATM == YES)
{
annView.image = [UIImage imageNamed:#"map_atmicon.png"];
}
else if(newLoc.isBranch == YES)
{
annView.image = [UIImage imageNamed:#"map_branchicon.png"];
}
//annView.enabled = YES;
annView.tag = mapView.tag;
annView.canShowCallout =YES;
}
countATMandBranch++;
return annView;
}
If any one aware of this kind of issue please reply to my question.
This might be an offset issue.
When you use a custom image for an MKAnnotationView it will by default position it in the center. If you are using a custom 'pin' image this isn't what you want - you want the bottom of the pin to point to the location, rather than the center. If you don't change the offset, when you zoom in/out the position of the annotation will appear to change in comparison to where you think it should be.
You should therefore make sure you've set an appropriate centerOffset on your annotation view. I don't see you setting it in the code above, so unless you want your image to be centered exactly on the coordinates required this is probably what's causing it.

Centralized the code

- (void) setTheMap
{
myMap.mapType = MKMapTypeStandard;
[myMap setDelegate:self];
CLLocationCoordinate2D coord = {latitude:myValue , longitude:myValue };
MKCoordinateSpan span = {latitudeDelta:0.05f , longitudeDelta: 0.05f};
MKCoordinateRegion region = {coord , span};
[myMap setRegion:region];
[self.view addSubview:myMap];
PantryAnnotation *dis = [[PantryAnnotation alloc] init];
dis.coordinate = region.center;
dis.title = row.panName;
dis.subTitle = row.geo_lat;
[myMap addAnnotation:dis];
}
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id<MKAnnotation>)annotation
{ MKPinAnnotationView *pview = nil;
if (annotation != myMap.userLocation)
{
static NSString *defalt = #"Volunteer";
pview = (MKPinAnnotationView *)[myMap dequeueReusableAnnotationViewWithIdentifier:defalt];
if ( pview == nil )
pview = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defalt] autorelease];
pview.pinColor = MKPinAnnotationColorRed;
pview.canShowCallout = YES;
pview.animatesDrop = YES;
}
else
{
[myMap.userLocation setTitle:#"I am Here"];
}
return pview;
}
The above gives me map view with annotation pin. I have to write this code in more than 8 files. Can any one tell me how can I centralized this code ? I mean to create only one class and by object of that class I can add the map in any other view.
Thanks..
Since the rest of your code is not clear, it is hard to give advice, but you may try to analyze it first;
what is common in these 8 code parts, and what is different?
Then you should figure out if you need to create and hold references to any local variables, lets say your map objects, or something like that.
If so, then subclassing would be the first choice to look at,
if not then an Obj-C category would probably do (http://macdevelopertips.com/objective-c/objective-c-categories.html). P.S: you cannot add member fields with this, only behavior (methods) are allowed.
If you need only objects with little to none behavior other than these, then you may make them plain objects holding the parameters only.
Or even you may use static methods like ( +(void) blahblah; ) just to be short, but dont do it unless you are sure that the behavior is generic in nature...
Well, a soup of advice here, if you provide more info, i can write in one of these directions in more details
good luck!

showsUserLocation returns pin instead of blue dot in iPhone simulator

This is my -mapView:viewForAnnotation method which drops pins when i create annotation views. But when i set mapView.showsUserLocation = YES; in -viewDidLoad, i get a pin dropped on Infinite Loop (expected - in simulator) and not the normal blue dot.
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{
MKAnnotationView *anno = nil;
//create a pin annotation view
MKPinAnnotationView *pin=[[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"pin"]autorelease];
[pin setPinColor:MKPinAnnotationColorRed];
pin.animatesDrop=YES;
pin.canShowCallout = YES;
pin.calloutOffset = CGPointMake(-5, 5);
anno = pin;
return anno;
}
How can i get it to drop pins and show the blue dot as well?
Thanks
Really simple to fix, although unsure if this is the correct way to do it...
if (annotation == mapView.userLocation){
return nil; //default to blue dot
}
Similar to the other answer, here's something close:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
NSString *annotationType = [NSString stringWithCString:object_getClassName(annotation)];
if ([annotationType compare:#"NSKVONotifying_MKUserLocation"] == 0)
return nil;
...
}
Of course, use something like this at your own risk. It could stop working tomorrow if Apple decided to change that name.
Often you use your own class of annotation to look up information related to the annotation. In that case, to only handle your own annotations, use something like
if ([annotation isKindOfClass:[MapLocation class]]) {}