diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi index 9ae44b2d451..d510d25c03e 100644 --- a/gyp/platform-ios.gypi +++ b/gyp/platform-ios.gypi @@ -60,6 +60,7 @@ '../platform/ios/MGLUserLocationAnnotationView.h', '../platform/ios/MGLUserLocationAnnotationView.m', '../include/mbgl/ios/MGLAnnotationImage.h', + '../platform/ios/MGLAnnotationImage_Private.h', '../platform/ios/MGLAnnotationImage.m', '../platform/ios/MGLCategoryLoader.h', '../platform/ios/MGLCategoryLoader.m', diff --git a/include/mbgl/ios/MGLAnnotationImage.h b/include/mbgl/ios/MGLAnnotationImage.h index 70bf8b75991..f48a3cfb457 100644 --- a/include/mbgl/ios/MGLAnnotationImage.h +++ b/include/mbgl/ios/MGLAnnotationImage.h @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN /** @name Getting and Setting Attributes */ /** The image to be displayed for the annotation. */ -@property (nonatomic, readonly) UIImage *image; +@property (nonatomic, strong) UIImage *image; /** The string that identifies that this annotation image is reusable. (read-only) * diff --git a/platform/ios/MGLAnnotationImage.m b/platform/ios/MGLAnnotationImage.m index cd211c52e61..374ed162fb9 100644 --- a/platform/ios/MGLAnnotationImage.m +++ b/platform/ios/MGLAnnotationImage.m @@ -1,9 +1,9 @@ -#import "MGLAnnotationImage.h" +#import "MGLAnnotationImage_Private.h" @interface MGLAnnotationImage () -@property (nonatomic) UIImage *image; -@property (nonatomic) NSString *reuseIdentifier; +@property (nonatomic, strong) NSString *reuseIdentifier; +@property (nonatomic, weak) id delegate; @end @@ -28,4 +28,9 @@ - (instancetype)initWithImage:(UIImage *)image reuseIdentifier:(NSString *)reuse return self; } +- (void)setImage:(UIImage *)image { + _image = image; + [self.delegate annotationImageNeedsRedisplay:self]; +} + @end diff --git a/platform/ios/MGLAnnotationImage_Private.h b/platform/ios/MGLAnnotationImage_Private.h new file mode 100644 index 00000000000..f22a9ac4e20 --- /dev/null +++ b/platform/ios/MGLAnnotationImage_Private.h @@ -0,0 +1,18 @@ +#import "MGLAnnotationImage.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol MGLAnnotationImageDelegate + +@required +- (void)annotationImageNeedsRedisplay:(MGLAnnotationImage *)annotationImage; + +@end + +@interface MGLAnnotationImage (Private) + +@property (nonatomic, weak) id delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 63cca9210e1..799ab32b474 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -36,6 +36,7 @@ #import "MGLUserLocationAnnotationView.h" #import "MGLUserLocation_Private.h" #import "MGLAccountManager_Private.h" +#import "MGLAnnotationImage_Private.h" #import "MGLMapboxEvents.h" #import "SMCalloutView.h" @@ -120,7 +121,8 @@ @interface MGLMapView () + MGLMultiPointDelegate, + MGLAnnotationImageDelegate> @property (nonatomic) EAGLContext *context; @property (nonatomic) GLKView *glView; @@ -2144,6 +2146,7 @@ - (void)addAnnotations:(NS_ARRAY_OF(id ) *)annotations { self.annotationImagesByIdentifier[annotationImage.reuseIdentifier] = annotationImage; [self installAnnotationImage:annotationImage]; + annotationImage.delegate = self; } NSString *symbolName = [MGLAnnotationSpritePrefix stringByAppendingString:annotationImage.reuseIdentifier]; @@ -2687,6 +2690,17 @@ - (void)showAnnotations:(NS_ARRAY_OF(id ) *)annotations animated: animated:animated]; } +#pragma mark Annotation Image Delegate + +- (void)annotationImageNeedsRedisplay:(MGLAnnotationImage *)annotationImage +{ + // remove sprite + NSString *symbolName = [MGLAnnotationSpritePrefix stringByAppendingString:annotationImage.reuseIdentifier]; + _mbglMap->removeAnnotationIcon(symbolName.UTF8String); + [self installAnnotationImage:annotationImage]; + _mbglMap->update(mbgl::Update::Annotations); +} + #pragma mark - User Location - - (void)setShowsUserLocation:(BOOL)showsUserLocation diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index a85021b774a..6538cb8e9ee 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -159,6 +159,11 @@ void AnnotationManager::addIcon(const std::string& name, std::shared_ptr); + void removeIcon(const std::string& name); double getTopOffsetPixelsForIcon(const std::string& name); SpriteAtlas& getSpriteAtlas() { return spriteAtlas; } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 4336c2556d1..ee22e5f8c9d 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -380,7 +380,7 @@ void Map::addAnnotationIcon(const std::string& name, std::shared_ptraddIcon(name, sprite); } + +void MapContext::removeAnnotationIcon(const std::string& name) { + assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); + data.getAnnotationManager()->removeIcon(name); +} double MapContext::getTopOffsetPixelsForAnnotationIcon(const std::string& name) { assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); @@ -298,7 +303,7 @@ void MapContext::onLowMemory() { style->onLowMemory(); asyncInvalidate.send(); } - + void MapContext::onTileDataChanged() { assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); updateFlags |= Update::Repaint; diff --git a/src/mbgl/map/map_context.hpp b/src/mbgl/map/map_context.hpp index 8e0dbd80c09..554765eac6b 100644 --- a/src/mbgl/map/map_context.hpp +++ b/src/mbgl/map/map_context.hpp @@ -52,6 +52,7 @@ class MapContext : public Style::Observer { // Annotations void addAnnotationIcon(const std::string&, std::shared_ptr); + void removeAnnotationIcon(const std::string&); double getTopOffsetPixelsForAnnotationIcon(const std::string&); void updateAnnotations(); diff --git a/src/mbgl/sprite/sprite_atlas.cpp b/src/mbgl/sprite/sprite_atlas.cpp index 6ebebb9507c..202218f51ce 100644 --- a/src/mbgl/sprite/sprite_atlas.cpp +++ b/src/mbgl/sprite/sprite_atlas.cpp @@ -187,8 +187,12 @@ void SpriteAtlas::updateDirty() { // The two names match; Holder& holder = imageIterator->second; holder.texture = spriteIterator->second; - copy(holder, imageIterator->first.second); - + if (holder.texture != nullptr) { + copy(holder, imageIterator->first.second); + } else { + images.erase(imageIterator); + } + ++imageIterator; // Don't advance the spriteIterator because there might be another sprite with the same // name, but a different wrap value.