1
1
#import " FFFastImageView.h"
2
2
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
9
15
10
16
- (id ) init {
11
17
self = [super init ];
@@ -14,82 +20,95 @@ - (id) init {
14
20
return self;
15
21
}
16
22
17
- - (void )setResizeMode : (RCTResizeMode)resizeMode
18
- {
23
+ - (void )dealloc {
24
+ [NSNotificationCenter .defaultCenter removeObserver: self ];
25
+ }
26
+
27
+ - (void )setResizeMode : (RCTResizeMode)resizeMode {
19
28
if (_resizeMode != resizeMode) {
20
29
_resizeMode = resizeMode;
21
30
self.contentMode = (UIViewContentMode)resizeMode;
22
31
}
23
32
}
24
33
25
- - (void )setOnFastImageLoadEnd : (RCTBubblingEventBlock )onFastImageLoadEnd {
34
+ - (void )setOnFastImageLoadEnd : (RCTDirectEventBlock )onFastImageLoadEnd {
26
35
_onFastImageLoadEnd = onFastImageLoadEnd;
27
- if (hasCompleted) {
36
+ if (self. hasCompleted ) {
28
37
_onFastImageLoadEnd (@{});
29
38
}
30
39
}
31
40
32
- - (void )setOnFastImageLoad : (RCTBubblingEventBlock )onFastImageLoad {
41
+ - (void )setOnFastImageLoad : (RCTDirectEventBlock )onFastImageLoad {
33
42
_onFastImageLoad = onFastImageLoad;
34
- if (hasCompleted) {
35
- _onFastImageLoad (onLoadEvent);
43
+ if (self. hasCompleted ) {
44
+ _onFastImageLoad (self. onLoadEvent );
36
45
}
37
46
}
38
47
39
48
- (void )setOnFastImageError : (RCTDirectEventBlock)onFastImageError {
40
49
_onFastImageError = onFastImageError;
41
- if (hasErrored) {
50
+ if (self. hasErrored ) {
42
51
_onFastImageError (@{});
43
52
}
44
53
}
45
54
46
- - (void )setOnFastImageLoadStart : (RCTBubblingEventBlock )onFastImageLoadStart {
47
- if (_source && !hasSentOnLoadStart) {
55
+ - (void )setOnFastImageLoadStart : (RCTDirectEventBlock )onFastImageLoadStart {
56
+ if (_source && !self. hasSentOnLoadStart ) {
48
57
_onFastImageLoadStart = onFastImageLoadStart;
49
58
onFastImageLoadStart (@{});
50
- hasSentOnLoadStart = YES ;
59
+ self. hasSentOnLoadStart = YES ;
51
60
} else {
52
61
_onFastImageLoadStart = onFastImageLoadStart;
53
- hasSentOnLoadStart = NO ;
62
+ self. hasSentOnLoadStart = NO ;
54
63
}
55
64
}
56
65
57
66
- (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];
64
80
}
65
81
}
66
82
67
83
- (void )setSource : (FFFastImageSource *)source {
68
84
if (_source != source) {
69
85
_source = source;
70
86
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
+
71
90
// Load base64 images.
72
91
NSString * url = [_source.url absoluteString ];
73
92
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 ;
77
96
} {
78
- hasSentOnLoadStart = NO ;
97
+ self. hasSentOnLoadStart = NO ;
79
98
}
80
99
UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL: _source.url]];
81
100
[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
+ });
87
106
}
88
- hasCompleted = YES ;
107
+ self. hasCompleted = YES ;
89
108
[self sendOnLoad: image];
90
109
91
- if (_onFastImageLoadEnd ) {
92
- _onFastImageLoadEnd (@{});
110
+ if (self. onFastImageLoadEnd ) {
111
+ self. onFastImageLoadEnd (@{});
93
112
}
94
113
return ;
95
114
}
@@ -100,8 +119,7 @@ - (void)setSource:(FFFastImageSource *)source {
100
119
}];
101
120
102
121
// Set priority.
103
- SDWebImageOptions options = 0 ;
104
- options |= SDWebImageRetryFailed;
122
+ SDWebImageOptions options = SDWebImageRetryFailed;
105
123
switch (_source.priority ) {
106
124
case FFFPriorityLow:
107
125
options |= SDWebImageLowPriority;
@@ -125,52 +143,55 @@ - (void)setSource:(FFFastImageSource *)source {
125
143
break ;
126
144
}
127
145
128
- if (_onFastImageLoadStart ) {
129
- _onFastImageLoadStart (@{});
130
- hasSentOnLoadStart = YES ;
146
+ if (self. onFastImageLoadStart ) {
147
+ self. onFastImageLoadStart (@{});
148
+ self. hasSentOnLoadStart = YES ;
131
149
} {
132
- hasSentOnLoadStart = NO ;
150
+ self. hasSentOnLoadStart = NO ;
133
151
}
134
- hasCompleted = NO ;
135
- hasErrored = NO ;
152
+ self. hasCompleted = NO ;
153
+ self. hasErrored = NO ;
136
154
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 (@{});
164
179
}
165
- } else {
166
- hasCompleted = YES ;
167
- [self sendOnLoad: image];
168
- if (_onFastImageLoadEnd) {
169
- _onFastImageLoadEnd (@{});
180
+ if (weakSelf.onFastImageLoadEnd ) {
181
+ weakSelf.onFastImageLoadEnd (@{});
170
182
}
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 (@{});
171
192
}
172
- }];
173
- }
193
+ }
194
+ }];
174
195
}
175
196
176
197
@end
0 commit comments