I'm having trouble understanding what I'm doing wrong when setting my custom pin images.
Here is my mapView:viewForAnnotation method that I have. As you can see, I want different images to display based on the value in my Location object. For the majority this works, and the correct images are being associated with the correct pins. However, on occasion they are just plain wrong and seem to be randomly assigned.
Any guidance would be appreciated!
EDIT: I've updated my code below in line with latest comments. It's still causing the same behaviour....
- (MKAnnotationView *)mapView:(MKMapView *)MapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
if([annotation isKindOfClass:[ADClusterAnnotation class]])
{
MKAnnotationView * pinView = (MKAnnotationView *)[MapView dequeueReusableAnnotationViewWithIdentifier:#"ADClusterableAnnotation"];
if (pinView == nil)
{
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"ADClusterableAnnotation"];
} else
{
pinView.annotation = annotation;
}
Location *selectedLocation = [[[(ADClusterAnnotation *) annotation cluster] annotation] annotation];
UIButton *rightCallout = [UIButton buttonWithType:UIButtonTypeCustom];
rightCallout.frame = CGRectMake(0, 0, 23, 23);
rightCallout.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
rightCallout.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
pinView.image = nil;
pinView.canShowCallout = YES;
[rightCallout setImage:[UIImage imageNamed:#"star.png"] forState:UIControlStateNormal];
pinView.rightCalloutAccessoryView = rightCallout;
if (selectedLocation.number.intValue > 4)
{
pinView.image = [UIImage imageNamed:#"image3.png"];
}
else if (selectedLocation.number.intValue >= 1)
{
pinView.image = [UIImage imageNamed:#"image2.png"];
}
else if (selectedLocation.number.intValue < 1)
{
pinView.image = [UIImage imageNamed:#"image3.png"];
}
return pinView;
}
return nil;
}
OK. I've made it much simpler than the starting point, but I've still got the exact same problem! It's is really driving me crazy, I have no idea what I'm doing wrong. Please please can someone help.
btw, I'm using the following for clustering my annotations (I don't know if this is causing issue!): https://github.com/applidium/ADClusterMapView
You are only setting the pinView.image if pinView is hill after trying to dequeue it. Which will work for the first few until the page is full. If you then scroll down the ones on screen go out of view and get reused for the new rows that appear. Because they are pulled from the queue you are not changing their image and you see the image from the rows that have gone away.
Basically you should build a new pinView if you can't dequeue one, but you still need to set the pinView.image either way, so close off the if statement like this.
if (!pinView) {
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation
} reuseIdentifier:#"ADClusterableAnnotation"];
Related
Hi am trying to change the annotation detail view(show in map image) into a custom design like the second image.
How can i change that background image and all?
my current code is
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation {
mapView.showsUserLocation = YES;
if([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString *identifier = #"myAnnotation";
MKPinAnnotationView * annotationView = (MKPinAnnotationView*)[_MAPVIEW dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annotationView)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.pinColor = MKPinAnnotationColorPurple;
annotationView.canShowCallout = YES;
}else {
annotationView.annotation = annotation;
}
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[infoButton addTarget:self action:#selector(showDetailView) forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView = infoButton;
UIImageView *imageV=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"pin.png"]];
annotationView.leftCalloutAccessoryView=imageV;
return annotationView;
}
current annotation detail view design(when i click on pin then i can see the annotation detail view )
but i want something like this design
please help me.
I have a strange behavior when loading annotations in a map.
I have a custom annotation that loads different images according to a property.
During the development of the project i have changed one of this image (removed the resource from the project and added the new one)
When i debug the app with the simulator it work fine. loading the correct images.
On the device it still load the old image i removed. (the image is no longer in the project!)
I cleaned the device unistalling the app, and i still have the problem.
Here the code where i set the images in the annotations.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"ParkingLocation";
if ([annotation isKindOfClass:[ParkingLocation class]]) {
ParkingLocation *parkLoc = (ParkingLocation *)annotation;
if ([parkLoc.type isEqualToString:#"CHIUSO"])
{
parkLoc.imagePin = [UIImage imageNamed:#"locator_parking"];
}
else
{
if ([parkLoc.type isEqualToString:#"PARCOMETRO"])
parkLoc.imagePin = [UIImage imageNamed:#"locator_strada"];
else
parkLoc.imagePin = [UIImage imageNamed:#"locator_general"];
}
MKAnnotationView *annotationView = (MKAnnotationView *) [self.myMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image = parkLoc.imagePin;
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
} else {
annotationView.image = parkLoc.imagePin;
annotationView.annotation = annotation;
}
return annotationView;
}
return nil;
}
The image i changed in the project is named "locator_strada"
Anyone had the same behavior? Because i'm newbie about iOS and Objective-C , maybe i'm not considering some memory issue?
Thanks
I want to display my custom annotations in the map and my current location as the standard pin in the map view with the blue color.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"MapPin";
if ([annotation isKindOfClass:[MyAnnotations class]]) {
MyAnnotations *ann= annotation;
MKAnnotationView *annotationView = (MKAnnotationView *) [self.map dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
if (ann.custom){
annotationView.image = [UIImage imageNamed:#"custom.png"];
}else{
//?? annotationView.image = [UIImage imageNamed:#"bluePin.png?"];
}
} else {
annotationView.annotation = annotation;
}
if(ann.custom){
UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[nextButton addTarget:self action:#selector(annotationPicked) forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView=nextButton;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.multipleTouchEnabled = NO;
return annotationView;
}
return nil;
}
If the custom property is to distinguish between your annotations and the map view's user location, that case is already handled by the first if which checks the annotation's class and the custom property would be unnecessary.
The map view's user location annotation is of type MKUserLocation so the code will return nil in that case and the map view will show the standard blue dot (assuming showsUserLocation is YES).
However, if the custom property is to distinguish between two types of your own annotations, then one problem is that it doesn't handled re-used annotation views properly (when annotationView != nil).
When an annotation view is re-used, its image and rightCalloutAccessoryView may not be right for the current annotation so those properties need to be set (or cleared) whether a view is being re-used or not. For example:
if ([annotation isKindOfClass:[MyAnnotations class]]) {
MyAnnotations *ann= annotation;
MKAnnotationView *annotationView = (MKAnnotationView *) [self.map dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.multipleTouchEnabled = NO;
} else {
annotationView.annotation = annotation;
}
//set view properties that depend on annotation-specific properties
//regardless of whether view is new or re-used...
if (ann.custom)
{
annotationView.image = [UIImage imageNamed:#"custom.png"];
UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[nextButton addTarget:self action:#selector(annotationPicked) forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView=nextButton;
}
else
{
annotationView.image = [UIImage imageNamed:#"bluePin.png"];
annotationView.rightCalloutAccessoryView = nil;
}
return annotationView;
}
Though if the custom property is just to separate all your annotations from the map view's user location, it's unnecessary in the first place (as long as you check the annotation's class and set showsUserLocation to YES).
may be you put custom code in this event .because when you click on current location annotation this method calls and may be bacause of that code application crashes.
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
}
Thanks.
I have a problem with the custom image on MapKit annotation. Building a sample project where I am performing the same test, it works properly (although the drop effect and the custom image do not work).
But when I use exactly the same function on my map view project, the custom image does not appear. I noticed that the color pin change function MKPinAnnotationColorPurple does not work either. Is it possible that it depends on some project properties?
The code is:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MyLocation class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.animatesDrop= NO;
annotationView.image=[UIImage imageNamed:#"arrest.png" ];//here we use a nice image instead of the default pins
annotationView.canShowCallout = YES;
UIButton *btnDetails = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//[btnDetails addTarget:self action:#selector(prova) forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView=btnDetails;
return annotationView;
}
return nil;
}
The UIButtonTypeDetailDisclosure does not appear either (in other projects it does).
Having trouble with MKAnnotation. Have a custom pinview and works fine for the first loading. Go to remove pins and then reload same pins they change colors. Im adding pins from two different DB's and works just fine. Once removed and then add each array separately the second array takes the first arrays custom pin instead of the one assigned.
- (MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"pin";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"stores.png"]];
pinView.leftCalloutAccessoryView = profileIconView;
NSString *badgestringss = #"8 reviews";
customBadge1 = [CustomBadge customBadgeWithString:badgestringss
withStringColor:[UIColor whiteColor]
withInsetColor:RGB(255, 51, 0)
withBadgeFrame:YES
withBadgeFrameColor:[UIColor whiteColor]
withScale:1.0
withShining:YES];
[customBadge1 setFrame:CGRectMake(100, 1, 85, 15)];
[pinView.leftCalloutAccessoryView addSubview:customBadge1];
if(setStoreOrShops==NO){
pinView.image = [UIImage imageNamed:#"stores.png"]; //as suggested by Squatch
}
else if (setStoreOrShops==YES){
pinView.image = [UIImage imageNamed:#"shops.png"];
}
else {
[mapView.userLocation setTitle:#"Current Location"];
}
}
return pinView;
}
have searched all over but cant seem to get an example to work or an idea where this is breaking down. Thanks for any help.
I'm not sure what you mean by changing color, as I don't know what your CustomBadge code does or what your images look like. However, the problem could be that you are applying conditional logic inside of your initial setup of the view. Later when dequeReusableAnnotationViewWithIdentifier: actually returns something, it's been configured for something else.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKAnnotationView *pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"default"];
if (pinView == nil) {
// CONFIGURE ONCE
// things that are set up once and never change
}
// CONFIGURE EVERY VIEW
// view configurations that change every pin
}
You need to take the code that sets your images out of the "configure once" section and put it in the "configure for every view" section. Otherwise, every time you make a call to dequeue a reusable view you can get something that is configured incorrectly.
got it fixed this way
MyAnnotation *myAnnot = (MyAnnotation *)annotation;
if (myAnnot.mappin == #"42")
customPinView.image = [UIImage imageNamed:#"shops.png"];
else
customPinView.image = [UIImage imageNamed:#"stores.png"];