Skip to content

Commit 48e4afc

Browse files
ericapplychristopherdro
authored andcommitted
Issue1176 improve ios marker performance by X100 (react-native-maps#1187)
* Issue1176 attempt to fix UI lag success by re-using UIImage * Now use NSMutableDictionary instead of single UIImage * appearAnimation happen at init rather than setIcon * Init NSMutableDictionary * Remove reference to other app
1 parent 1abc76c commit 48e4afc

File tree

3 files changed

+92
-64
lines changed

3 files changed

+92
-64
lines changed

lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m

Lines changed: 16 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#import "AIRGMSMarker.h"
1313
#import "AIRGoogleMapCallout.h"
1414
#import "DummyView.h"
15+
#import "GlobalVars.h"
1516

1617
CGRect unionRect(CGRect a, CGRect b) {
1718
return CGRectMake(
@@ -36,6 +37,7 @@ - (instancetype)init
3637
if ((self = [super init])) {
3738
_realMarker = [[AIRGMSMarker alloc] init];
3839
_realMarker.fakeMarker = self;
40+
_realMarker.appearAnimation = kGMSMarkerAnimationPop;
3941
}
4042
return self;
4143
}
@@ -92,6 +94,18 @@ - (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex
9294
[super insertReactSubview:(UIView*)dummySubview atIndex:atIndex];
9395
}
9496

97+
- (void)setIcon:(UIImage*)image {
98+
CGImageRef cgref = [image CGImage];
99+
CIImage *cim = [image CIImage];
100+
101+
if (cim == nil && cgref == NULL) {
102+
// image does not contain image data
103+
_realMarker.icon = [GMSMarker markerImageWithColor:UIColor.blueColor];
104+
} else {
105+
_realMarker.icon = image;
106+
}
107+
}
108+
95109
- (void)removeReactSubview:(id<RCTComponent>)dummySubview {
96110
UIView* subview = ((DummyView*)dummySubview).view;
97111

@@ -188,70 +202,8 @@ - (void)setOpacity:(double)opacity
188202

189203
- (void)setImageSrc:(NSString *)imageSrc
190204
{
191-
_imageSrc = imageSrc;
192-
193-
if (_reloadImageCancellationBlock) {
194-
_reloadImageCancellationBlock();
195-
_reloadImageCancellationBlock = nil;
196-
}
197-
198-
if (!_imageSrc) {
199-
if (_iconImageView) [_iconImageView removeFromSuperview];
200-
return;
201-
}
202-
203-
if (!_iconImageView) {
204-
// prevent glitch with marker (cf. https://github.com/airbnb/react-native-maps/issues/738)
205-
UIImageView *empyImageView = [[UIImageView alloc] init];
206-
_iconImageView = empyImageView;
207-
[self iconViewInsertSubview:_iconImageView atIndex:0];
208-
}
209-
210-
_reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc]
211-
size:self.bounds.size
212-
scale:RCTScreenScale()
213-
clipped:YES
214-
resizeMode:RCTResizeModeCenter
215-
progressBlock:nil
216-
partialLoadBlock:nil
217-
completionBlock:^(NSError *error, UIImage *image) {
218-
if (error) {
219-
// TODO(lmr): do something with the error?
220-
NSLog(@"%@", error);
221-
}
222-
dispatch_async(dispatch_get_main_queue(), ^{
223-
224-
// TODO(gil): This way allows different image sizes
225-
if (_iconImageView) [_iconImageView removeFromSuperview];
226-
227-
// ... but this way is more efficient?
228-
// if (_iconImageView) {
229-
// [_iconImageView setImage:image];
230-
// return;
231-
// }
232-
233-
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
234-
235-
// TODO: w,h or pixel density could be a prop.
236-
float density = 1;
237-
float w = image.size.width/density;
238-
float h = image.size.height/density;
239-
CGRect bounds = CGRectMake(0, 0, w, h);
240-
241-
imageView.contentMode = UIViewContentModeScaleAspectFit;
242-
[imageView setFrame:bounds];
243-
244-
// NOTE: sizeToFit doesn't work instead. Not sure why.
245-
// TODO: Doing it this way is not ideal because it causes things to reshuffle
246-
// when the image loads IF the image is larger than the UIView.
247-
// Shouldn't required images have size info automatically via RN?
248-
CGRect selfBounds = unionRect(bounds, self.bounds);
249-
[self setFrame:selfBounds];
250-
251-
_iconImageView = imageView;
252-
[self iconViewInsertSubview:imageView atIndex:0];
253-
});
254-
}];
205+
UIImage * image = [[GlobalVars sharedInstance] getSharedUIImage:imageSrc];
206+
[self setIcon:image];
255207
}
256208

257209
- (void)setTitle:(NSString *)title {

lib/ios/AirGoogleMaps/GlobalVars.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// GlobalVars.h
3+
//
4+
// Created by Eric Kim on 2017-04-04.
5+
// Copyright © 2017 Apply Digital. All rights reserved.
6+
//
7+
8+
#import <Foundation/Foundation.h>
9+
#import <UIKit/UIKit.h>
10+
11+
@interface GlobalVars : NSObject
12+
{
13+
NSMutableDictionary *dict;
14+
}
15+
16+
+ (GlobalVars *)sharedInstance;
17+
18+
- (UIImage *)getSharedUIImage:(NSString *)imageSrc;
19+
20+
@property(strong, nonatomic, readwrite) NSMutableDictionary *dict;
21+
22+
@end

lib/ios/AirGoogleMaps/GlobalVars.m

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// GlobalVars.m
3+
//
4+
// Created by Eric Kim on 2017-04-04.
5+
// Copyright © 2017 Apply Digital. All rights reserved.
6+
//
7+
8+
#import "GlobalVars.h"
9+
10+
@implementation GlobalVars
11+
12+
@synthesize dict = _dict;
13+
14+
+ (GlobalVars *)sharedInstance {
15+
static dispatch_once_t onceToken;
16+
static GlobalVars *instance = nil;
17+
dispatch_once(&onceToken, ^{
18+
instance = [[GlobalVars alloc] init];
19+
});
20+
return instance;
21+
}
22+
23+
- (UIImage *)getSharedUIImage:(NSString *)imageSrc {
24+
25+
UIImage* cachedImage = dict[imageSrc];
26+
27+
CGImageRef cgref = [cachedImage CGImage];
28+
CIImage *cim = [cachedImage CIImage];
29+
30+
if (cim == nil && cgref == NULL) {
31+
UIImage *newImage;
32+
if ([imageSrc hasPrefix:@"http://"] || [imageSrc hasPrefix:@"https://"]){
33+
NSURL *url = [NSURL URLWithString:imageSrc];
34+
NSData *data = [NSData dataWithContentsOfURL:url];
35+
newImage = [UIImage imageWithData:data scale:[UIScreen mainScreen].scale];
36+
} else {
37+
newImage = [UIImage imageWithContentsOfFile:imageSrc];
38+
}
39+
dict[imageSrc] = newImage;
40+
return newImage;
41+
} else {
42+
return cachedImage;
43+
}
44+
}
45+
46+
- (id)init {
47+
self = [super init];
48+
if (self) {
49+
dict = [[NSMutableDictionary alloc] init];
50+
}
51+
return self;
52+
}
53+
54+
@end

0 commit comments

Comments
 (0)