11#import " FFFastImageView.h"
22
3- @implementation FFFastImageView {
4- BOOL hasSentOnLoadStart;
5- BOOL hasCompleted;
6- BOOL hasErrored;
7- NSDictionary * onLoadEvent;
8- }
3+
4+ @interface FFFastImageView ()
5+
6+ @property (nonatomic , assign ) BOOL hasSentOnLoadStart;
7+ @property (nonatomic , assign ) BOOL hasCompleted;
8+ @property (nonatomic , assign ) BOOL hasErrored;
9+
10+ @property (nonatomic , strong ) NSDictionary * onLoadEvent;
11+
12+ @end
13+
14+ @implementation FFFastImageView
915
1016- (id ) init {
1117 self = [super init ];
@@ -14,82 +20,95 @@ - (id) init {
1420 return self;
1521}
1622
17- - (void )setResizeMode : (RCTResizeMode)resizeMode
18- {
23+ - (void )dealloc {
24+ [NSNotificationCenter .defaultCenter removeObserver: self ];
25+ }
26+
27+ - (void )setResizeMode : (RCTResizeMode)resizeMode {
1928 if (_resizeMode != resizeMode) {
2029 _resizeMode = resizeMode;
2130 self.contentMode = (UIViewContentMode)resizeMode;
2231 }
2332}
2433
25- - (void )setOnFastImageLoadEnd : (RCTBubblingEventBlock )onFastImageLoadEnd {
34+ - (void )setOnFastImageLoadEnd : (RCTDirectEventBlock )onFastImageLoadEnd {
2635 _onFastImageLoadEnd = onFastImageLoadEnd;
27- if (hasCompleted) {
36+ if (self. hasCompleted ) {
2837 _onFastImageLoadEnd (@{});
2938 }
3039}
3140
32- - (void )setOnFastImageLoad : (RCTBubblingEventBlock )onFastImageLoad {
41+ - (void )setOnFastImageLoad : (RCTDirectEventBlock )onFastImageLoad {
3342 _onFastImageLoad = onFastImageLoad;
34- if (hasCompleted) {
35- _onFastImageLoad (onLoadEvent);
43+ if (self. hasCompleted ) {
44+ _onFastImageLoad (self. onLoadEvent );
3645 }
3746}
3847
3948- (void )setOnFastImageError : (RCTDirectEventBlock)onFastImageError {
4049 _onFastImageError = onFastImageError;
41- if (hasErrored) {
50+ if (self. hasErrored ) {
4251 _onFastImageError (@{});
4352 }
4453}
4554
46- - (void )setOnFastImageLoadStart : (RCTBubblingEventBlock )onFastImageLoadStart {
47- if (_source && !hasSentOnLoadStart) {
55+ - (void )setOnFastImageLoadStart : (RCTDirectEventBlock )onFastImageLoadStart {
56+ if (_source && !self. hasSentOnLoadStart ) {
4857 _onFastImageLoadStart = onFastImageLoadStart;
4958 onFastImageLoadStart (@{});
50- hasSentOnLoadStart = YES ;
59+ self. hasSentOnLoadStart = YES ;
5160 } else {
5261 _onFastImageLoadStart = onFastImageLoadStart;
53- hasSentOnLoadStart = NO ;
62+ self. hasSentOnLoadStart = NO ;
5463 }
5564}
5665
5766- (void )sendOnLoad : (UIImage *)image {
58- onLoadEvent = @{
59- @" width" :[NSNumber numberWithDouble: image.size.width],
60- @" height" :[NSNumber numberWithDouble: image.size.height]
61- };
62- if (_onFastImageLoad) {
63- _onFastImageLoad (onLoadEvent);
67+ self.onLoadEvent = @{
68+ @" width" :[NSNumber numberWithDouble: image.size.width],
69+ @" height" :[NSNumber numberWithDouble: image.size.height]
70+ };
71+ if (self.onFastImageLoad ) {
72+ self.onFastImageLoad (self.onLoadEvent );
73+ }
74+ }
75+
76+ - (void )imageDidLoadObserver : (NSNotification *)notification {
77+ FFFastImageSource *source = notification.object ;
78+ if (source != nil && source.url != nil ) {
79+ [self sd_setImageWithURL: source.url];
6480 }
6581}
6682
6783- (void )setSource : (FFFastImageSource *)source {
6884 if (_source != source) {
6985 _source = source;
7086
87+ // Attach a observer to refresh other FFFastImageView instance sharing the same source
88+ [NSNotificationCenter .defaultCenter addObserver: self selector: @selector (imageDidLoadObserver: ) name: source.url.absoluteString object: nil ];
89+
7190 // Load base64 images.
7291 NSString * url = [_source.url absoluteString ];
7392 if (url && [url hasPrefix: @" data:image" ]) {
74- if (_onFastImageLoadStart ) {
75- _onFastImageLoadStart (@{});
76- hasSentOnLoadStart = YES ;
93+ if (self. onFastImageLoadStart ) {
94+ self. onFastImageLoadStart (@{});
95+ self. hasSentOnLoadStart = YES ;
7796 } {
78- hasSentOnLoadStart = NO ;
97+ self. hasSentOnLoadStart = NO ;
7998 }
8099 UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL: _source.url]];
81100 [self setImage: image];
82- if (_onFastImageProgress ) {
83- _onFastImageProgress (@{
84- @" loaded" : @(1 ),
85- @" total" : @(1 )
86- });
101+ if (self. onFastImageProgress ) {
102+ self. onFastImageProgress (@{
103+ @" loaded" : @(1 ),
104+ @" total" : @(1 )
105+ });
87106 }
88- hasCompleted = YES ;
107+ self. hasCompleted = YES ;
89108 [self sendOnLoad: image];
90109
91- if (_onFastImageLoadEnd ) {
92- _onFastImageLoadEnd (@{});
110+ if (self. onFastImageLoadEnd ) {
111+ self. onFastImageLoadEnd (@{});
93112 }
94113 return ;
95114 }
@@ -100,8 +119,7 @@ - (void)setSource:(FFFastImageSource *)source {
100119 }];
101120
102121 // Set priority.
103- SDWebImageOptions options = 0 ;
104- options |= SDWebImageRetryFailed;
122+ SDWebImageOptions options = SDWebImageRetryFailed;
105123 switch (_source.priority ) {
106124 case FFFPriorityLow:
107125 options |= SDWebImageLowPriority;
@@ -125,52 +143,55 @@ - (void)setSource:(FFFastImageSource *)source {
125143 break ;
126144 }
127145
128- if (_onFastImageLoadStart ) {
129- _onFastImageLoadStart (@{});
130- hasSentOnLoadStart = YES ;
146+ if (self. onFastImageLoadStart ) {
147+ self. onFastImageLoadStart (@{});
148+ self. hasSentOnLoadStart = YES ;
131149 } {
132- hasSentOnLoadStart = NO ;
150+ self. hasSentOnLoadStart = NO ;
133151 }
134- hasCompleted = NO ;
135- hasErrored = NO ;
152+ self. hasCompleted = NO ;
153+ self. hasErrored = NO ;
136154
137- // Load the new source.
138- // This will work for:
139- // - https://
140- // - file:///var/containers/Bundle/Application/50953EA3-CDA8-4367-A595-DE863A012336/ReactNativeFastImageExample.app/assets/src/images/fields.jpg
141- // - file:///var/containers/Bundle/Application/545685CB-777E-4B07-A956-2D25043BC6EE/ReactNativeFastImageExample.app/assets/src/images/plankton.gif
142- // - file:///Users/dylan/Library/Developer/CoreSimulator/Devices/61DC182B-3E72-4A18-8908-8A947A63A67F/data/Containers/Data/Application/AFC2A0D2-A1E5-48C1-8447-C42DA9E5299D/Documents/images/E1F1D5FC-88DB-492F-AD33-B35A045D626A.jpg"
143- [self sd_setImageWithURL: _source.url
144- placeholderImage: nil
145- options: options
146- progress: ^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
147- if (_onFastImageProgress) {
148- _onFastImageProgress (@{
149- @" loaded" : @(receivedSize),
150- @" total" : @(expectedSize)
151- });
152- }
153- } completed: ^(UIImage * _Nullable image,
154- NSError * _Nullable error,
155- SDImageCacheType cacheType,
156- NSURL * _Nullable imageURL) {
157- if (error) {
158- hasErrored = YES ;
159- if (_onFastImageError) {
160- _onFastImageError (@{});
161- }
162- if (_onFastImageLoadEnd) {
163- _onFastImageLoadEnd (@{});
155+ [self downloadImage: _source options: options];
156+ }
157+ }
158+
159+ - (void )downloadImage : (FFFastImageSource *) source options : (SDWebImageOptions) options {
160+ __weak typeof (self) weakSelf = self; // Always use a weak reference to self in blocks
161+ [self sd_setImageWithURL: _source.url
162+ placeholderImage: nil
163+ options: options
164+ progress: ^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
165+ if (weakSelf.onFastImageProgress ) {
166+ weakSelf.onFastImageProgress (@{
167+ @" loaded" : @(receivedSize),
168+ @" total" : @(expectedSize)
169+ });
170+ }
171+ } completed: ^(UIImage * _Nullable image,
172+ NSError * _Nullable error,
173+ SDImageCacheType cacheType,
174+ NSURL * _Nullable imageURL) {
175+ if (error) {
176+ weakSelf.hasErrored = YES ;
177+ if (weakSelf.onFastImageError ) {
178+ weakSelf.onFastImageError (@{});
164179 }
165- } else {
166- hasCompleted = YES ;
167- [self sendOnLoad: image];
168- if (_onFastImageLoadEnd) {
169- _onFastImageLoadEnd (@{});
180+ if (weakSelf.onFastImageLoadEnd ) {
181+ weakSelf.onFastImageLoadEnd (@{});
170182 }
183+ } else {
184+ weakSelf.hasCompleted = YES ;
185+ [weakSelf sendOnLoad: image];
186+
187+ // Alert other FFFastImageView component sharing the same URL
188+ [NSNotificationCenter .defaultCenter postNotificationName: source.url.absoluteString object: source];
189+
190+ if (weakSelf.onFastImageLoadEnd ) {
191+ weakSelf.onFastImageLoadEnd (@{});
171192 }
172- }];
173- }
193+ }
194+ }];
174195}
175196
176197@end
0 commit comments