Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Changing image property of MGLAnnotationImage doesn't update sprite #4556

Closed
alexagat opened this issue Mar 31, 2016 · 14 comments
Closed

Changing image property of MGLAnnotationImage doesn't update sprite #4556

alexagat opened this issue Mar 31, 2016 · 14 comments
Labels
archived Archived because of inactivity bug gl-ios iOS Mapbox Maps SDK for iOS

Comments

@alexagat
Copy link

When I update the image property on a MGLAnnotationImage, for example in the didSelectAnnotation function:

func mapView(mapView: MGLMapView, didSelectAnnotation annotation: MGLAnnotation) {
    annotationsTitlesAndImages[annotation.title!!]!.image = UIImage(named: "map-pin-active")!
}

...I see the below block of code in mapbox-gl framework run, but the annotation image does not update:

- (void)setImage:(UIImage *)image {
    _image = image;
    [self.delegate annotationImageNeedsRedisplay:self];
}

I believe it should update the annotation's image on the fly without any type of manual refresh.

The issue is referenced:
#2210
#3146

@1ec5 1ec5 added bug iOS Mapbox Maps SDK for iOS labels Mar 31, 2016
@1ec5 1ec5 added this to the ios-v3.3.0 milestone Apr 3, 2016
@RomainQuidet
Copy link
Contributor

I tested it on objC, it's working for me.

@friedbunny
Copy link
Contributor

Replacing an annotation image is bit cumbersome — it’s currently not necessarily as simple as just changing the image property.

Here’s an a WIP example of how to replace an annotation image in Swift.

The key points:

  • The annotation image should be an instance of MGLAnnotationImage.
  • You should be checking reuse identifiers.
  • Use the annotation object that comes with the mapView:didSelectAnnotation: delegate method.

@1ec5
Copy link
Contributor

1ec5 commented May 25, 2016

Replacing an annotation image is bit cumbersome — it’s currently not necessarily as simple as just changing the image property.

This should work following #3835. Please let us know if setting the image property isn’t working in the v3.3.0 alphas.

@millenbop
Copy link

millenbop commented Nov 23, 2016

This is still an issue with ios-v3.3.7 static, so please reopen.

My code is below:

- (nullable MGLAnnotationImage *)mapView:(nonnull MGLMapView *)mapView imageForAnnotation:(nonnull id<MGLAnnotation>)annotation
{
    MapAnnotation* a = annotation;
    NSString* identifier = [NSString stringWithFormat:@"%f,%f", a.coordinate.latitude, a.coordinate.longitude];
    NSString* imageName = nil;
    
    if ([self.selected containsObject:a.userData])
    {
        imageName = @"marker-red.png";
    }
    else
    {
        imageName = @"marker-green.png";
    }
    
    MGLAnnotationImage* image = [mapView dequeueReusableAnnotationImageWithIdentifier:identifier];
    
    if (!image)
    {
        image = [MGLAnnotationImage annotationImageWithImage:[UIImage imageNamed:imageName] reuseIdentifier:identifier];
    }
    
    return image;
}

- (void)mapView:(MGLMapView *)mapView didSelectAnnotation:(id<MGLAnnotation>)annotation
{
    MapAnnotation* a = annotation;
    NSString* identifier = [NSString stringWithFormat:@"%f,%f", a.coordinate.latitude, a.coordinate.longitude];
    
    if (![self.selected containsObject:a.userData])
    {
        [self.selected addObject:a.userData];
        
        MGLAnnotationImage* annotationImage = [mapView dequeueReusableAnnotationImageWithIdentifier:identifier];
        annotationImage.image = [UIImage imageNamed:@"marker-red.png"];
    }
   
}

- (void)mapView:(MGLMapView *)mapView didDeselectAnnotation:(id<MGLAnnotation>)annotation
{
    MapAnnotation* a = annotation;
    NSString* identifier = [NSString stringWithFormat:@"%f,%f", a.coordinate.latitude, a.coordinate.longitude];
    
    if ([self.selected containsObject:a.userData])
    {
        [self.selected removeObject:a.userData];
        
        MGLAnnotationImage* annotationImage = [mapView dequeueReusableAnnotationImageWithIdentifier:identifier];
        annotationImage.image = [UIImage imageNamed:@"marker-green.png"];
    }
}

@1ec5 1ec5 removed this from the ios-v3.3.0 milestone Nov 23, 2016
@1ec5 1ec5 reopened this Nov 23, 2016
@Channel76
Copy link

This is also true if you try to change the pin size for an annotation image that is already "drawn" on the map with the same ReuseId. Even if you remove and re-add the annotation, the size of the pin doesn't change. In order to see the pin with the new size, you have to restart the app...

@1ec5
Copy link
Contributor

1ec5 commented Jan 14, 2017

#7618 tracks this issue more generally for style images in the runtime styling API.

@millenbop, before I re-close this issue as a reverse duplicate of #7618, can you confirm whether the marker-red.png and marker-green.png images you were using had differing dimensions?

@millenbop
Copy link

They have the same dimensions:

marker-green
marker-red
marker-yellow

@nrubin999
Copy link

nrubin999 commented Aug 28, 2017

@1ec5 What's the status of this? Trying to update image of MGLAnnotationImage with no success. Image has same dimensions.

@1ec5
Copy link
Contributor

1ec5 commented Aug 30, 2017

I can reproduce this issue in iosapp in eedd909 (post-v3.6.2, pre-v3.6.3) with the following diff:

diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 992b7d587..adc6b7c44 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -1777,8 +1777,14 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
         return;
     }
 
-    MGLPointAnnotation *point = (MGLPointAnnotation *)annotation;
-    point.coordinate = [self.mapView convertPoint:self.mapView.center toCoordinateFromView:self.mapView];
+//    MGLPointAnnotation *point = (MGLPointAnnotation *)annotation;
+//    point.coordinate = [self.mapView convertPoint:self.mapView.center toCoordinateFromView:self.mapView];
+    
+    NSString *title = [(MGLPointAnnotation *)annotation title];
+    if (!title.length) return;
+    NSString *lastTwoCharacters = [title substringFromIndex:title.length - 2];
+    MGLAnnotationImage *image = [mapView dequeueReusableAnnotationImageWithIdentifier:lastTwoCharacters];
+    image.image = [self imageWithText:lastTwoCharacters backgroundColor:[UIColor orangeColor]];
 }
 
 - (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style

Interestingly, if I uncomment the line that changes the annotation’s coordinate, the image does update – just for that particular annotation – by virtue of the call to mbgl::Map::updateAnnotation().

Digging in further, it does appear that -[MGLMapView annotationImageNeedsRedisplay:] and -installAnnotationImage: are working as they always have, by calling mbgl::Map::removeAnnotationImage() followed by addAnnotationImage() with the same image ID. If I remove this line, all the annotations associated with the annotation image update as expected – but only when deselecting the annotation or moving the viewport, which is weird.

diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index af7122fc1..236e50f39 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -4106,11 +4106,6 @@ public:
     NSString *fallbackReuseIdentifier = MGLDefaultStyleMarkerSymbolName;
     NSString *fallbackIconIdentifier = [MGLAnnotationSpritePrefix stringByAppendingString:fallbackReuseIdentifier];
 
-    // Remove the old icon from the style.
-    if ( ! [iconIdentifier isEqualToString:fallbackIconIdentifier]) {
-        _mbglMap->removeAnnotationImage(iconIdentifier.UTF8String);
-    }
-
     if (annotationImage.image)
     {
         // Add the new icon to the style.
@@ -4126,6 +4121,11 @@ public:
     }
     else
     {
+        // Remove the old icon from the style.
+        if ( ! [iconIdentifier isEqualToString:fallbackIconIdentifier]) {
+            _mbglMap->removeAnnotationImage(iconIdentifier.UTF8String);
+        }
+        
         // Add the default icon to the style if necessary.
         annotationImage.styleIconIdentifier = fallbackIconIdentifier;
         if ( ! [self dequeueReusableAnnotationImageWithIdentifier:MGLDefaultStyleMarkerSymbolName])

Since the image replacement feature was originally implemented, a formal style image API was added with the expectation that a sprite image would never be removed while in use. I think removing the call to removeAnnotationImage() is an appropriate fix, but we’ll need to figure out why the update only happens on deselection or camera changes and also test some edge cases like setting image to nil.

@ohwhen
Copy link

ohwhen commented Oct 22, 2017

Also running into this issue, using build 3.6.4. The image doesn't refresh automatically..the only workaround I found that works is removing and adding the annotation again.

mapView.removeAnnotation(annotation)
mapView.addAnnotation(annotation)

@1ec5
Copy link
Contributor

1ec5 commented Nov 14, 2017

we’ll need to figure out why the update only happens on deselection or camera changes

Pretty sure this was because I had merely moved the call to removeAnnotationImage() instead of deleting it outright. #10372 deletes the call to that method, which I think is the better fix.

@stale stale bot added the archived Archived because of inactivity label Nov 3, 2018
@sassiwalid
Copy link

sassiwalid commented Nov 28, 2018

my problem is when I select an annotation in the mapbox mapview the state changed to selected and the image of the annotation for this I wrote this delegate method

func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {

    if let castAnnotation = annotation as? MyCustomPointAnnotation {
        if (!castAnnotation.willUseImage) {
            return
        }
        for mapAnn in mapView.annotations!
        {
            castAnnotation.selected = false
        if ((mapAnn.coordinate.longitude == annotation.coordinate.longitude) && (mapAnn.coordinate.latitude == annotation.coordinate.latitude))
        {
            castAnnotation.selected = true
            castAnnotation.willUseImage = true
            mapView.removeAnnotation(annotation)
            mapView.addAnnotation(castAnnotation)
        }

    }
    }

} 

the addAnnotation method fire this imageForAnnotation method: func mapView(_ mapView: func mapView(_ mapView: MGLMapView, imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? {

    if let castAnnotation = annotation as? MyCustomPointAnnotation {
        if (!castAnnotation.willUseImage) {
            return nil;
        }
        if (!castAnnotation.selected == true) {
            
            let annotationImage = MGLAnnotationImage(image: UIImage(named: "pin_deselected")!, reuseIdentifier: String(describing: annotation.coordinate))
            annotationImage.image = textToImage(drawText: castAnnotation.stepId, inImage: (annotationImage.image)!, atPoint: CGPoint(x: 10, y: 5))
            return annotationImage
        }else{
            
            let annotationImage = MGLAnnotationImage(image: UIImage(named: "pin_selected")!, reuseIdentifier: String(describing: annotation.coordinate))
            annotationImage.image = textToImage(drawText: castAnnotation.stepId, inImage: (annotationImage.image)!, atPoint: CGPoint(x: 10, y: 5))
            return annotationImage
        }
    }
    return nil
}

It's fire correctly the second case but the pin image doesn't change!!!! I didn't know why??

@stale stale bot removed the archived Archived because of inactivity label Nov 28, 2018
@stale stale bot added the archived Archived because of inactivity label Aug 27, 2019
@stale
Copy link

stale bot commented Aug 27, 2019

This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

@stale stale bot closed this as completed Aug 27, 2019
@jmkiley jmkiley reopened this Aug 27, 2019
@stale stale bot removed the archived Archived because of inactivity label Aug 27, 2019
@stale stale bot added the archived Archived because of inactivity label May 20, 2020
@stale
Copy link

stale bot commented May 22, 2020

This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

@stale stale bot closed this as completed May 22, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
archived Archived because of inactivity bug gl-ios iOS Mapbox Maps SDK for iOS
Projects
None yet
Development

No branches or pull requests