Bug fix: icon image caching does not work properly
MODIFY
plugin.xml
plugin.xml
<?xml version='1.0' encoding='utf-8'?>
-<plugin id="cordova-plugin-googlemaps" version="2.0.0-beta3-20170810-1904" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
+<plugin id="cordova-plugin-googlemaps" version="2.0.0-beta3-20170811-1937" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
<name>cordova-plugin-googlemaps</name>
<js-module name="BaseClass" src="www/BaseClass.js">
<runs />
<source-file src="src/ios/GoogleMaps/MyPluginLayerDebugView.m" />
<header-file src="src/ios/GoogleMaps/MyPluginScrollView.h" />
<source-file src="src/ios/GoogleMaps/MyPluginScrollView.m" />
+ <header-file src="src/ios/GoogleMaps/UIImageCache.h" />
+ <source-file src="src/ios/GoogleMaps/UIImageCache.m" />
<config-file target="*-Info.plist" parent="Google Maps API Key">
<string>$API_KEY_FOR_IOS</string>

MODIFY
src/android/plugin/google/maps/AsyncLoadImage.java
src/android/plugin/google/maps/AsyncLoadImage.java
@@ -127,13 +127,14 @@ public class AsyncLoadImage extends AsyncTask<Void, Void, AsyncLoadImage.AsyncLo
mOptions.url = PluginUtil.getAbsolutePathFromCDVFilePath(resourceApi, mOptions.url);
}
- this.currentPageUrl = webView.getUrl();
- Log.d(TAG, "-->currentPageUrl = " + this.currentPageUrl);
+ this.currentPageUrl = CordovaGoogleMaps.CURRENT_URL; //webView.getUrl();
+ //Log.d(TAG, "-->currentPageUrl = " + this.currentPageUrl);
- View browserView = webView.getView();
- String browserViewName = browserView.getClass().getName();
- this.userAgent = "";
+ //View browserView = webView.getView();
+ //String browserViewName = browserView.getClass().getName();
+ this.userAgent = "Mozilla";
+ /*
if("org.xwalk.core.XWalkView".equals(browserViewName) ||
"org.crosswalk.engine.XWalkCordovaView".equals(browserViewName)) {
@@ -154,6 +155,7 @@ public class AsyncLoadImage extends AsyncTask<Void, Void, AsyncLoadImage.AsyncLo
} else {
this.userAgent = ((WebView) webView.getEngine().getView()).getSettings().getUserAgentString();
}
+ */
}
@@ -162,12 +164,25 @@ public class AsyncLoadImage extends AsyncTask<Void, Void, AsyncLoadImage.AsyncLo
int mWidth = mOptions.width;
int mHeight = mOptions.height;
String iconUrl = mOptions.url;
+ String orgIconUrl = iconUrl;
Bitmap image = null;
if (iconUrl == null) {
return null;
}
+ String cacheKey = null;
+ cacheKey = getCacheKey(orgIconUrl, mWidth, mHeight);
+
+ image = getBitmapFromMemCache(cacheKey);
+ if (image != null) {
+ AsyncLoadImageResult result = new AsyncLoadImageResult();
+ result.image = image;
+ result.cacheHit = true;
+ result.cacheKey = cacheKey;
+ return result;
+ }
+
//Log.d(TAG, "--> iconUrl = " + iconUrl);
//--------------------------------
// Load image from local path
@@ -225,15 +240,8 @@ public class AsyncLoadImage extends AsyncTask<Void, Void, AsyncLoadImage.AsyncLo
}
}
-
- String cacheKey = null;
- if (iconUrl.indexOf("http") == 0) {
- //--------------------------------
- // Load image from the Internet
- //--------------------------------
- try {
cacheKey = getCacheKey(iconUrl, mWidth, mHeight);
- URL url = new URL(iconUrl);
+
image = getBitmapFromMemCache(cacheKey);
if (image != null) {
AsyncLoadImageResult result = new AsyncLoadImageResult();
@@ -243,6 +251,15 @@ public class AsyncLoadImage extends AsyncTask<Void, Void, AsyncLoadImage.AsyncLo
return result;
}
+ cacheKey = getCacheKey(orgIconUrl, mWidth, mHeight);
+
+ if (iconUrl.indexOf("http") == 0) {
+ //--------------------------------
+ // Load image from the Internet
+ //--------------------------------
+ try {
+ URL url = new URL(iconUrl);
+
boolean redirect = true;
HttpURLConnection http = null;
String cookies = null;
@@ -356,16 +373,6 @@ public class AsyncLoadImage extends AsyncTask<Void, Void, AsyncLoadImage.AsyncLo
} else {
//Log.d(TAG, "--> iconUrl = " + iconUrl);
- cacheKey = getCacheKey(iconUrl, mWidth, mHeight);
-
- image = getBitmapFromMemCache(cacheKey);
- if (image != null) {
- AsyncLoadImageResult result = new AsyncLoadImageResult();
- result.image = image;
- result.cacheHit = true;
- result.cacheKey = cacheKey;
- return result;
- }
if (iconUrl.indexOf("data:image/") == 0 && iconUrl.contains(";base64,")) {

MODIFY
src/android/plugin/google/maps/CordovaGoogleMaps.java
src/android/plugin/google/maps/CordovaGoogleMaps.java
@@ -72,7 +72,7 @@ public class CordovaGoogleMaps extends CordovaPlugin implements ViewTreeObserver
private GoogleApiClient googleApiClient = null;
public boolean initialized = false;
public PluginManager pluginManager;
- private String CURRENT_URL;
+ public static String CURRENT_URL;
public static final HashMap<String, String> semaphore = new HashMap<String, String>();
@SuppressLint("NewApi") @Override
@@ -237,6 +237,14 @@ public class CordovaGoogleMaps extends CordovaPlugin implements ViewTreeObserver
}
+ @Override
+ public boolean onOverrideUrlLoading(String url) {
+ Log.d(TAG, "onOverrideUrlLoading = " + url);
+ CURRENT_URL = url;
+ return false;
+ }
+
+
@Override
public void onScrollChanged() {
if (mPluginLayout == null) {
@@ -252,7 +260,7 @@ public class CordovaGoogleMaps extends CordovaPlugin implements ViewTreeObserver
@Override
public boolean execute(final String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
- cordova.getThreadPool().execute(new Runnable() {
+ cordova.getThreadPool().submit(new Runnable() {
@Override
public void run() {
try {

MODIFY
src/android/plugin/google/maps/PluginMarker.java
src/android/plugin/google/maps/PluginMarker.java
@@ -245,6 +245,8 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
markerOptions.visible(opts.getBoolean("visible"));
properties.put("isVisible", markerOptions.isVisible());
}
+ } else {
+ markerOptions.visible(true);
}
if (opts.has("draggable")) {
markerOptions.draggable(opts.getBoolean("draggable"));
@@ -998,7 +1000,7 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
options.height = height;
options.noCaching = noCaching;
- final AsyncLoadImage task = new AsyncLoadImage(cordova, webView, options, new AsyncLoadImageInterface() {
+ AsyncLoadImage task = new AsyncLoadImage(cordova, webView, options, new AsyncLoadImageInterface() {
@Override
public void onPostExecute(AsyncLoadImage.AsyncLoadImageResult result) {
if (result == null || result.image == null) {
@@ -1076,12 +1078,7 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
callback.onPostExecute(marker);
}
});
- cordova.getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
task.execute();
- }
- });
iconLoadingTasks.add(task);
}

MODIFY
src/ios/GoogleMaps/GoogleMapsViewController.h
src/ios/GoogleMaps/GoogleMapsViewController.h
@property (nonatomic) BOOL isRenderedAtOnce;
@property (nonatomic) GMSMarker* activeMarker;
@property (nonatomic, readwrite, strong) NSString *mapDivId;
-@property (atomic, strong) NSMutableDictionary* objects;
+@property (nonatomic, strong) NSMutableDictionary* objects;
@property (atomic, strong) NSOperationQueue *executeQueue;

MODIFY
src/ios/GoogleMaps/GoogleMapsViewController.m
src/ios/GoogleMaps/GoogleMapsViewController.m
self.clickable = YES;
self.isRenderedAtOnce = NO;
self.mapDivId = nil;
- self.objects = [NSMutableDictionary dictionary];
+ self.objects = [[NSMutableDictionary alloc] init];
self.executeQueue = [NSOperationQueue new];
self.executeQueue.maxConcurrentOperationCount = 10;

MODIFY
src/ios/GoogleMaps/PluginMarker.h
src/ios/GoogleMaps/PluginMarker.h
#import "CordovaGoogleMaps.h"
#import "MyPlgunProtocol.h"
#import "PluginUtil.h"
+#import "UIImageCache.h"
#import "NSData+Base64.h"
@interface PluginMarker : CDVPlugin<MyPlgunProtocol>
-@property (nonatomic, strong) NSCache* icons;
-@property (nonatomic) NSMutableDictionary* iconCacheKeys;
@property (nonatomic) BOOL initialized;
@property (nonatomic, strong) GoogleMapsViewController* mapCtrl;

MODIFY
src/ios/GoogleMaps/PluginMarker.m
src/ios/GoogleMaps/PluginMarker.m
self.initialized = YES;
[super pluginInitialize];
// Initialize this plugin
- self.icons = [[NSCache alloc]init];
- self.icons.totalCostLimit = 3 * 1024 * 1024 * 1024; // 3MB = Cache for image
- self.iconCacheKeys = [NSMutableDictionary dictionary];
}
- (void)pluginUnload
[self.mapCtrl.objects removeObjectForKey:key];
}
- [self.icons removeAllObjects];
- self.icons = nil;
+ [[UIImageCache sharedInstance] removeAllCachedImages];
key = nil;
keys = nil;
NSString *iconCacheKey = [NSString stringWithFormat:@"marker_icon_%@", marker.userData];
NSString *propertyId = [NSString stringWithFormat:@"marker_property_%@", marker.userData];
[self.mapCtrl.objects objectForKey: marker.userData];
- [self.mapCtrl.objects removeObjectForKey:iconCacheKey];
+ //[self.mapCtrl.objects removeObjectForKey:iconCacheKey];
[self.mapCtrl.objects removeObjectForKey:propertyId];
marker.map = nil;
marker = nil;
if ([self.mapCtrl.objects objectForKey:iconCacheKey]) {
+
NSString *cacheKey = [self.mapCtrl.objects objectForKey:iconCacheKey];
- if ([self.mapCtrl.objects objectForKey:iconCacheKey]) {
- [self.mapCtrl.objects removeObjectForKey:iconCacheKey];
- if ([self.iconCacheKeys objectForKey:cacheKey]) {
- int count = [[self.iconCacheKeys objectForKey:cacheKey] intValue];
+
+ if ([[UIImageCache sharedInstance].iconCacheKeys objectForKey:cacheKey]) {
+ int count = [[[UIImageCache sharedInstance].iconCacheKeys objectForKey:cacheKey] intValue];
count--;
+ NSLog(@"iconCacheKey = %@, count = %d", cacheKey, count);
if (count < 1) {
- UIImage *image = [self.icons objectForKey:cacheKey];
- if (image != nil) {
- image = nil;
- }
- [self.icons removeObjectForKey:cacheKey];
- [self.iconCacheKeys removeObjectForKey:cacheKey];
+ [[UIImageCache sharedInstance] removeCachedImageForKey:cacheKey];
+ [[UIImageCache sharedInstance].iconCacheKeys removeObjectForKey:cacheKey];
} else {
- [self.iconCacheKeys setObject:[NSNumber numberWithInt:count] forKey:cacheKey];
- }
+ [[UIImageCache sharedInstance].iconCacheKeys setObject:[NSNumber numberWithInt:count] forKey:cacheKey];
}
}
+
if ([self.mapCtrl.objects objectForKey:iconCacheKey]) {
[self.mapCtrl.objects removeObjectForKey:iconCacheKey];
}
if (self.mapCtrl.debuggable) {
NSLog(@"iconPath = %@", iconPath);
}
+ NSString *iconCacheKey = [NSString stringWithFormat:@"%lu/%d,%d", (unsigned long)iconPath.hash, (int)width, (int)height];
+ UIImage *image = [[UIImageCache sharedInstance] getCachedImageForKey:iconCacheKey];
+
+ //---------------------------------------
+ // If the image is cached, return it
+ //---------------------------------------
+ if (image != nil) {
+
+ NSString *iconKey = [NSString stringWithFormat:@"marker_icon_%@", marker.userData];
+ [self.mapCtrl.objects setObject:iconCacheKey forKey:iconKey];
+
+ int count = [[[UIImageCache sharedInstance].iconCacheKeys objectForKey:iconCacheKey] intValue];
+ count++;
+ [[UIImageCache sharedInstance].iconCacheKeys setObject:[NSNumber numberWithInt:count] forKey:iconCacheKey];
+ NSLog(@"---> iconCacheKey = %@, count = %d", iconCacheKey, count);
+
+
+ if ([iconProperty objectForKey:@"label"]) {
+ image = [self drawLabel:image labelOptions:[iconProperty objectForKey:@"label"]];
+ }
- NSRange range = [iconPath rangeOfString:@"data:image"];
- if (range.location != 0) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ marker.icon = image;
+
+ CGFloat anchorX = 0;
+ CGFloat anchorY = 0;
+ // The `anchor` property for the icon
+ if ([iconProperty valueForKey:@"anchor"]) {
+ NSArray *points = [iconProperty valueForKey:@"anchor"];
+ anchorX = [[points objectAtIndex:0] floatValue] / image.size.width;
+ anchorY = [[points objectAtIndex:1] floatValue] / image.size.height;
+ marker.groundAnchor = CGPointMake(anchorX, anchorY);
+ }
+
+ // The `infoWindowAnchor` property
+ if ([iconProperty valueForKey:@"infoWindowAnchor"]) {
+ NSArray *points = [iconProperty valueForKey:@"infoWindowAnchor"];
+ anchorX = [[points objectAtIndex:0] floatValue] / image.size.width;
+ anchorY = [[points objectAtIndex:1] floatValue] / image.size.height;
+ marker.infoWindowAnchor = CGPointMake(anchorX, anchorY);
+ }
+
+
+ // The `visible` property
+ if (iconProperty[@"visible"]) {
+ marker.map = self.mapCtrl.map;
+ }
+
+ if (animation) {
+ // Do animation, then send the result
+ [self setMarkerAnimation_:animation marker:marker callbackBlock:^(void) {
+ callbackBlock(YES, marker);
+ }];
+ } else {
+ // Send the result
+ callbackBlock(YES, marker);
+ }
+ });
+
+ return;
+ }
+
+ //
+ // Load icon from file or Base64 encoded strings
+ //
+
+ if ([iconPath rangeOfString:@"data:image/"].location != NSNotFound &&
+ [iconPath rangeOfString:@";base64,"].location != NSNotFound) {
+
+ NSArray *tmp = [iconPath componentsSeparatedByString:@","];
+
+ NSData *decodedData = [NSData dataFromBase64String:tmp[1]];
+ image = [[UIImage alloc] initWithData:decodedData];
+ if (width && height) {
+ image = [image resize:width height:height];
+ }
+ }
+
+ NSRange range;
+ if (image == nil && ![iconPath hasPrefix:@"http"]) {
if (![iconPath containsString:@"://"] &&
![iconPath hasPrefix:@"/"] &&
}
- UIImage *image;
-
range = [iconPath rangeOfString:@"://"];
if (range.location == 0) {
}
image = [UIImage imageNamed:iconPath];
+ }
+
+ if (image != nil) {
if (width && height) {
image = [image resize:width height:height];
}
- }
-
-
-
-
+ // Cache the icon image
+ NSString *iconKey = [NSString stringWithFormat:@"marker_icon_%@", marker.userData];
+ [[UIImageCache sharedInstance] cacheImage:image forKey:iconCacheKey];
+ [self.mapCtrl.objects setObject:iconCacheKey forKey:iconKey];
+ [[UIImageCache sharedInstance].iconCacheKeys setObject:[NSNumber numberWithInt:1] forKey:iconCacheKey];
+ NSLog(@"--->confirm: key: %@, iconCacheKey : %@", iconKey, [self.mapCtrl.objects objectForKey:iconKey]);
- //---------------------------------------
- // If the image is cached, return it
- //---------------------------------------
-
- NSString *iconCacheKey = [NSString stringWithFormat:@"%lu/%d,%d", (unsigned long)iconPath.hash, (int)width, (int)height];
- NSData *cache = [self.icons objectForKey:iconCacheKey];
- if (cache != nil) {
- int cacheHitCount = [[self.iconCacheKeys objectForKey:iconCacheKey] intValue];
- cacheHitCount++;
- [self.iconCacheKeys setObject:[NSNumber numberWithInt:cacheHitCount] forKey:iconCacheKey];
- UIImage *image = (UIImage *)cache;//[[UIImage alloc] initWithData:cache];
if ([iconProperty objectForKey:@"label"]) {
image = [self drawLabel:image labelOptions:[iconProperty objectForKey:@"label"]];
-
-
- if (iconPath) {
-
- if (self.mapCtrl.debuggable) {
- NSLog(@"iconPath = %@", iconPath);
- }
-
- NSRange range = [iconPath rangeOfString:@"http"];
- if (range.location != 0) {
- /**
- * Load icon from file or Base64 encoded strings
- */
-
- UIImage *image;
- if ([iconPath rangeOfString:@"data:image/"].location != NSNotFound &&
- [iconPath rangeOfString:@";base64,"].location != NSNotFound) {
-
- /**
- * Base64 icon
- */
- NSArray *tmp = [iconPath componentsSeparatedByString:@","];
-
- NSData *decodedData = [NSData dataFromBase64String:tmp[1]];
- image = [[UIImage alloc] initWithData:decodedData];
- if (width && height) {
- image = [image resize:width height:height];
- }
-
- } else {
- /**
- * Load the icon from local path
- */
-/*
- range = [iconPath rangeOfString:@"cdvfile://"];
- if (range.location != NSNotFound) {
-
- iconPath = [PluginUtil getAbsolutePathFromCDVFilePath:self.webView cdvFilePath:iconPath];
-
- if (iconPath == nil) {
- if (self.mapCtrl.debuggable) {
- NSLog(@"(debug)Can not convert '%@' to device full path.", iconPath);
- }
- //[self.commandDelegate sendPluginResult:pluginResult callbackId:callbackId];
- callbackBlock(NO, [NSString stringWithFormat:@"Can not convert '%@' to device full path.", iconPath]);
- return;
- }
- }
-
- range = [iconPath rangeOfString:@"://"];
- if (range.location == NSNotFound) {
-
- range = [iconPath rangeOfString:@"/"];
- if (range.location != 0) {
- // Get the current URL, then calculate the relative path.
- CDVViewController *cdvViewController = (CDVViewController*)self.viewController;
-
- id webview = cdvViewController.webView;
- NSString *clsName = [webview className];
- NSURL *url;
- if ([clsName isEqualToString:@"UIWebView"]) {
- url = ((UIWebView *)cdvViewController.webView).request.URL;
- } else {
- url = [webview URL];
- }
- NSString *currentURL = url.absoluteString;
- currentURL = [currentURL stringByDeletingLastPathComponent];
- currentURL = [currentURL stringByReplacingOccurrencesOfString:@"file:" withString:@""];
- currentURL = [currentURL stringByReplacingOccurrencesOfString:@"//" withString:@"/"];
- iconPath = [NSString stringWithFormat:@"file://%@/%@", currentURL, iconPath];
- } else {
- iconPath = [NSString stringWithFormat:@"file://%@", iconPath];
- }
- }
-
- range = [iconPath rangeOfString:@"file://"];
- if (range.location != NSNotFound) {
- iconPath = [iconPath stringByReplacingOccurrencesOfString:@"file://" withString:@""];
- NSFileManager *fileManager = [NSFileManager defaultManager];
- if (![fileManager fileExistsAtPath:iconPath]) {
- //if (self.mapCtrl.debuggable) {
- NSLog(@"(error)There is no file at '%@'.", iconPath);
- //}
- //[self.commandDelegate sendPluginResult:pluginResult callbackId:callbackId];
- callbackBlock(NO, [NSString stringWithFormat:@"There is no file at '%@'.", iconPath]);
- return;
- }
- }
-*/
- image = [UIImage imageNamed:iconPath];
-
- if (width && height) {
- image = [image resize:width height:height];
- }
- }
-
- // Cache the icon image
- NSData *imgData = UIImagePNGRepresentation(image);
- [self.icons setObject:image forKey:iconCacheKey cost:[imgData length]];
- imgData = nil;
- [self.mapCtrl.objects setObject:iconCacheKey forKey:[NSString stringWithFormat:@"marker_icon_%@", marker.userData]];
- [self.iconCacheKeys setObject:[NSNumber numberWithInt:1] forKey:iconCacheKey];
-
-
- if ([iconProperty objectForKey:@"label"]) {
- image = [self drawLabel:image labelOptions:[iconProperty objectForKey:@"label"]];
- }
-
- dispatch_async(dispatch_get_main_queue(), ^{
- marker.icon = image;
-
- CGFloat anchorX = 0;
- CGFloat anchorY = 0;
- // The `anchor` property for the icon
- if ([iconProperty valueForKey:@"anchor"]) {
- NSArray *points = [iconProperty valueForKey:@"anchor"];
- anchorX = [[points objectAtIndex:0] floatValue] / image.size.width;
- anchorY = [[points objectAtIndex:1] floatValue] / image.size.height;
- marker.groundAnchor = CGPointMake(anchorX, anchorY);
- }
-
- // The `infoWindowAnchor` property
- if ([iconProperty valueForKey:@"infoWindowAnchor"]) {
- NSArray *points = [iconProperty valueForKey:@"infoWindowAnchor"];
- anchorX = [[points objectAtIndex:0] floatValue] / image.size.width;
- anchorY = [[points objectAtIndex:1] floatValue] / image.size.height;
- marker.infoWindowAnchor = CGPointMake(anchorX, anchorY);
- }
-
-
- // The `visible` property
- if (iconProperty[@"visible"]) {
- marker.map = self.mapCtrl.map;
- }
-
- if (animation) {
- // Do animation, then send the result
- [self setMarkerAnimation_:animation marker:marker callbackBlock:^(void) {
- callbackBlock(YES, marker);
- }];
- } else {
- // Send the result
- callbackBlock(YES, marker);
- }
- });
- } else {
if (self.mapCtrl.debuggable) {
NSLog(@"---- Load the icon from over the internet");
}
- /***
- * Load the icon from over the internet
- */
- [self.iconCacheKeys setObject:[NSNumber numberWithInt:1] forKey:iconCacheKey];
+
+ //
+ // Load the icon from over the internet
+ //
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
if ([[iconProperty valueForKey:@"visible"] boolValue]) {
marker.map = self.mapCtrl.map;
}
- if ([self.iconCacheKeys objectForKey:iconCacheKey]) {
- [self.iconCacheKeys removeObjectForKey:iconCacheKey];
+ if ([[UIImageCache sharedInstance].iconCacheKeys objectForKey:iconCacheKey]) {
+ [[UIImageCache sharedInstance].iconCacheKeys removeObjectForKey:iconCacheKey];
}
callbackBlock(NO, [NSString stringWithFormat:@"Can not load image from '%@'.", url]);
}
// Cache the icon image
- NSData *imgData = UIImagePNGRepresentation(image);
- [self.icons setObject:image forKey:iconCacheKey cost:[imgData length]];
- imgData = nil;
- [self.mapCtrl.objects setObject:iconCacheKey forKey:[NSString stringWithFormat:@"marker_icon_%@", marker.userData]];
+ NSString *iconKey = [NSString stringWithFormat:@"marker_icon_%@", marker.userData];
+ [[UIImageCache sharedInstance] cacheImage:image forKey:iconCacheKey];
+ [self.mapCtrl.objects setObject:iconCacheKey forKey:iconKey];
+ [[UIImageCache sharedInstance].iconCacheKeys setObject:[NSNumber numberWithInt:1] forKey:iconCacheKey];;
+ NSLog(@"--->confirm: key: %@, iconCacheKey : %@", iconKey, [self.mapCtrl.objects objectForKey:iconKey]);
// Draw label
if ([iconProperty objectForKey:@"label"]) {
});
-
- }
- }
-
}
- (UIImage *)drawLabel:(UIImage *) image labelOptions:(NSDictionary *)labelOptions {
}
NSString *uniqueKey = url.absoluteString;
- NSData *cache = [self.icons objectForKey:uniqueKey];
- if (cache != nil) {
- UIImage *image = [[UIImage alloc] initWithData:cache];
+ UIImage *image = [[UIImageCache sharedInstance] getCachedImageForKey:uniqueKey];
+ if (image != nil) {
completionBlock(YES, image);
return;
}
NSURLSessionDataTask *getTask = [session dataTaskWithRequest:req
completionHandler:^(NSData *data, NSURLResponse *res, NSError *error) {
if ( !error ) {
- [self.icons setObject:data forKey:uniqueKey cost:data.length];
UIImage *image = [UIImage imageWithData:data];
+ [[UIImageCache sharedInstance] cacheImage:image forKey:uniqueKey];
completionBlock(YES, image);
} else {
completionBlock(NO, nil);

ADD
src/ios/GoogleMaps/UIImageCache.h
+//
+// UIImageCache
+// cordova-googlemaps-plugin v2
+//
+// Created by Masashi Katsumata.
+//
+//
+#ifndef UIImageCache_h
+#define UIImageCache_h
+
+#import <Foundation/Foundation.h>
+
+@interface UIImageCache : NSObject
+
++ (UIImageCache*)sharedInstance;
+@property (nonatomic) NSMutableDictionary* iconCacheKeys;
+
+// set
+- (void)cacheImage:(UIImage*)image forKey:(NSString*)key;
+// get
+- (UIImage*)getCachedImageForKey:(NSString*)key;
+// remove
+- (void)removeCachedImageForKey:(NSString*)key;
+// remove all
+- (void)removeAllCachedImages;
+@end
+
+
+#endif

ADD
src/ios/GoogleMaps/UIImageCache.m
+//
+// UIImageCache
+// cordova-googlemaps-plugin v2
+//
+// Created by Masashi Katsumata.
+//
+//
+#import "UIImageCache.h"
+
+static UIImageCache *sharedInstance;
+
+@interface UIImageCache ()
+@property (nonatomic, strong) NSCache *imageCache;
+@end
+
+@implementation UIImageCache
+
++ (UIImageCache*)sharedInstance {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ sharedInstance = [[UIImageCache alloc] init];
+ });
+ return sharedInstance;
+}
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ self.imageCache = [[NSCache alloc] init];
+ self.imageCache.totalCostLimit = 3 * 1024 * 1024 * 1024; // 3MB = Cache for image
+ self.iconCacheKeys = [NSMutableDictionary dictionary];
+ }
+ return self;
+}
+
+- (void)cacheImage:(UIImage*)image forKey:(NSString*)key {
+ NSData *imgData = UIImagePNGRepresentation(image);
+ [self.imageCache setObject:image forKey:key cost:[imgData length]];
+ imgData = nil;
+}
+
+- (UIImage*)getCachedImageForKey:(NSString*)key {
+ return [self.imageCache objectForKey:key];
+}
+- (void)removeCachedImageForKey:(NSString*)key {
+ [self.imageCache removeObjectForKey:key];
+}
+
+- (void)removeAllCachedImages:(NSString*)key {
+ [self.imageCache removeAllObjects];
+}
+
+
+@end

Bug fix: icon image caching does not work properly