showsUserLocation returns pin instead of blue dot in iPhone simulator - iphone

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]]) {}

Related

MKPinAnnotationView not moving while change location

I am working on location based application in which i need to move MKAnnotation Pin as per the change location. It means as user change location from once place to other the Annotation should be moved.
This is my code of annotation:
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[mV dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if (pinView == nil)
{
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID];
pinView.enabled = YES;
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
}
return pinView;
}
It drops the pin on the current location but when i move with device the location changed & also MKPolyline i have implement but Pin stays there.
see this image :
You can see in this the green pin is the start point & the other side is the current point. So the pin should be on the current point thats what i want.
I have searched & tried few of the solutions of stack but not able to solve my issue.
Any suggestions & help will be highly appreciated.
Thanks in advance.
I got the solution from #AnnaKarenina suggestions thank you so much.
What i have done is make my MKPinAnnotationView global & then :
pinView.annotation.coordinate = newLocation.coordinate;
This line i added into didUpdateToLocation method which allows annotation to get new location every time.
Thanks again.

User location image pin disappears most of time

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.

MKPinAnnotationView and custom classes conforming to the MKAnnotation protocol

I have created the following method for determining the view for my annotations in a map view.
- (MKAnnotationView *)mapView:(MKMapView *)mv viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
MKPinAnnotationView *pin;
if ([annotation isKindOfClass:[AnnotationsWithIndices class]])
{
int i = [(AnnotationsWithIndices *)annotation index];
if (i > currentCheckpointIndex )
{
pin = (MKPinAnnotationView *)[mv dequeueReusableAnnotationViewWithIdentifier:#"unvisited"];
if (!pin)
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"unvisited"];
}
[pin setPinColor:MKPinAnnotationColorRed];
}
if (i == currentCheckpointIndex)
{
pin = (MKPinAnnotationView *)[mv dequeueReusableAnnotationViewWithIdentifier:#"current"];
if (!pin)
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"];
}
[pin setPinColor:MKPinAnnotationColorGreen];
}
if (i < currentCheckpointIndex)
{
pin = (MKPinAnnotationView *)[mv dequeueReusableAnnotationViewWithIdentifier:#"visited"];
if (!pin)
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"visited"];
}
[pin setPinColor:MKPinAnnotationColorPurple];
}
[pin setAnimatesDrop:YES];
return [pin autorelease];
}
else
return nil;
}
The idea is that I want the different annotation views (pins) be of different colors depending on whether the user has visited them to signal which annotation to visit next.
This code works fine, but I have a few questions about it which I hope someone can answer.
Firstly, the MKPinAnnotations are dequeued from a map view and reused whenever possible. In the line doing so (which I have found in multiple blogs and forums)
pin = (MKPinAnnotationView *)[mv dequeueReusableAnnotationViewWithIdentifier:#"unvisited"];
I understand that the return value of the dequeueReusableAnnotationViewWithIdentifier: is an instance of MKAnnotationView, whereas pin is a pointer to an instance of MKPinAnnotationView (which is a subclass o MKAnnotationView). This, I guess, is why there is a 'cast' seemingly going on with the prefix (MKPinAnnotationView *) in front of the method call. Is this really a cast and in this case, is it not dangerous since the MKPinAnnotationView contains more instance variables (than MKAnnotationView) and hence more space in memory?
I have tried to find some information about this, but nowhere I have not found anyone explaining this in particular.
Furthermore, the pointer annotation is either of class MKUserLocation or of my own custom class AnnotationsWithIndices conforming to the MKAnnotation protocol. Now, in order to determine which color the annotation view should have I have added an instance variable called index into the AnnotationsWithIndices class. Now, when I call the getter for the index I write
int i = [(AnnotationsWithIndices *)annotation index];
Now, I basically have the same question about this. Is there a cast going on here or is it just to let the compiler know that it is ok to send the message index to annotation? I guess that the compiler expects annotation to be an id whereas it really is a pointer to an instance of AnnotationsWithIndices.
Of course I know that this is the case since the annotation will be of my custom class, and I also check this explicitly to be sure. Is the (AnnotationsWithIndices) there only to signal to the compiler that this is OK?
I have also tried to find information about this without luck.
I am very thankful for any answers on this.

add overlays to existing pins in viewcontroller.m

I'm new to programming and obj-c and currently working on a map based iphone app which will locate different sport facilities. I want each pin to show a different overlay, for instance a picture overlay will do fine, I'll add pics into the resource folder and I want each pin to reveal a different picture by clicking it. My example only includes one pin with its cordinates.
Now, I have now clue where to start, hope u can help me out!
thanks in advance :)
Here's my code:
[mapView addAnnotation:[MapLocation mapLocationtWithTitle:#"Beckomberga Sim och Sporthall" subtitle:#"Söderberga Allé 80" andCoordinate:(CLLocationCoordinate2D){ 59.35817, 17.89740 }]];
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if([annotation isKindOfClass:[MapLocation class]])
{
MKPinAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"PinAnnotation"];
pin.canShowCallout = YES;
pin.animatesDrop = NO;
pin.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pin.pinColor = MKPinAnnotationColorRed;
pin.pinColor = MKPinAnnotationColorGreen;
[pin autorelease];
return pin;
}
return nil;
}
Viktor,
Here is what you need to do:
Create a subobject of MKAnnotation that will represent your locations, SportsFacilityLocation
That object will contain title, subtitle, and location fields. This is to conform to the MKAnnotation protocol
Next you need an object that will be a subclass of MKAnnotationView, SportsFacilityMapView.
Finally in your viewForAnnotation delegate method you need to check each annotation type
and from that annotation type you will determine to return your SportsFacilityMapView
Check the docs on how to implement the Annotation and then AnnotationView. I have some example code at home that I will post later if you need it. Good Luck!

Several pin colors on same map in MKMapView

I have a MKMapView in my app with several pins on it and I'd like to set different colors for each pin. My view controller is implementing MKMapViewDelegate and I've defined viewForAnnotation method.
- (MKAnnotationView *) mapView:(MKMapView *)mapView
viewForAnnotation:(id <MKAnnotation>) annotation {
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:#"pin"];
annView.pinColor = MKPinAnnotationColorGreen;
return annView;
}
It works fine and changes pin color to green. However the color is changed for all pins and I'd like to color them with several colors (based on some criteria I'd define, lets assume I want to have odd pins green and even pins yellow or something as simple as that). How can this be achieved?
I've solved this issue by using images instead of pinColor. This way I can have as many pins as I want.
if(annotation.fillsYourCriteria)
annView.pinColor = MKPinAnnotationColorGreen;
else
annView.pinColor = MKPinAnnotationColorYellow;
return annView;
Something as simple as that?
I have met the same issue then I solved by using this code
if([[pinView.annotation title] isEqualToString:#"Current Location"])
{
pinView.pinColor = MKPinAnnotationColorRed;
}
else
{
pinView.pinColor = MKPinAnnotationColorPurple;
}