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
Related
i am using multiple annotation views with different images in my map view. Images are loading properly in simulator but not in device.i am not able to figure out the reason for this issue..following is my code
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString * const annotationIdentifier = #"CustomAnnotation";
annotationView1 = [mapUrCommView dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
MKAnnotationView *annotationView2 = nil;
if (annotationView1)
{
annotationView1.annotation = annotation;
if(mapUrCommView.userInteractionEnabled)
annotationView1.image = [UIImage imageNamed:#"MapPinDarkBlue75#2x.png"];// map-pin-black.png
else
{
//if(annotationView1.annotation == self.currentAnnotation|| annotation == self.previousAnnotation)
NSLog(#"in annotation view 1");
annotationView1.image = [UIImage imageNamed:#"mapDrawPoint#2x.png"];// Bluedot.png
}
annotationView1.tag=111;
return annotationView1;
}
else
{
annotationView2 = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
annotationView2.image = [UIImage imageNamed:#"MapPinDarkBlue75#2x.png"];// map-pin-black.png
annotationView2.canShowCallout = YES;
return annotationView2;
}
return nil;
}
here i am drawing physical boundaries for a location in my app...so annotation view 1 is view which i am drawing presently & annoation view 2 will be having all annotations custom view images(all annotations will be having same images) which i already drawn in past..custom annotaion images are loading fine in simulator but not in device
It's worked me for using custom class for annotation.. Please refer this sample Apple documentation.
1.) Allocate MapAnnotation
mapAnnotation = [[MapAnnotation alloc]init];
2.) Set Coordinate for your lat and long
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake([[NBCGPSLocation sharedInstance].gpsLatitude doubleValue], [[NBCGPSLocation sharedInstance].gpsLongitude doubleValue]);
[mapAnnotation setCoordinate:coord];
[self.mapSDKView addAnnotation:mapAnnotation];
3.) Now this delegate method will call once you go that lat and long location
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[CustomAnnotation class]])
{
if(!customAnnotationView)
customAnnotationView = [[MKAnnotationView alloc]init];
customAnnotationView.image = [UIImage imageNamed:#"locationCustom"];
customAnnotationView.annotation = annotation;
return customAnnotationView;
}
else
{
if(!annotationView)
annotationView = [[MKAnnotationView alloc]init];
annotationView.image = [UIImage imageNamed:#"locationIcon"];
annotationView.annotation = annotation;
return annotationView;
}
}
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"];
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 dont understand why the userLocation doesnt move when i set a costum image on it.
If i don't set an image, it uses the default pin blue and it works; i can see the userlocation moves when the postion changes.
here is my viewForAnnotation taken from an other post.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* AnnotationIdentifier = #"Annotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mk dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
}
else
{
pinView.annotation = annotation;
}
if (annotation == mk.userLocation)
pinView.image = [UIImage imageNamed:#"PositionPin.png"];
else
pinView.image = [UIImage imageNamed:#"PositionPin.png"];
return pinView;
}
This appears to be a bug in the map view (still present in iOS 6) where the user location coordinates no longer update when a custom annotation view is used (even though documentation suggests it will work).
A workaround is to use Core Location to get user location updates and create your own annotation (instead of using the map view's userLocation) and then supplying a custom image for it in viewForAnnotation.
See the answer to Custom Annotation view for userlocation not moving the mapview for more details and some sample code to implement the workaround.
In addition, note that when using a custom image for your annotation view, you should use MKAnnotationView instead of MKPinAnnotationView.
When using MKPinAnnotationView, it sometimes shows its default pin image instead of your custom image.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* AnnotationIdentifier = #"Annotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mk dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
}
pinView.annotation = annotation;
pinView.image = [UIImage imageNamed:#"PositionPin.png"];
return pinView;
}
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).