@@ -200,13 +200,20 @@ - (BOOL)_retrieveImageForEntity:(id <FICEntity>)entity withFormatName:(NSString
200200
201201 if (sourceImageURL != nil ) {
202202 // We check to see if this image is already being fetched.
203- NSMutableDictionary *requestDictionary = [_requests objectForKey: sourceImageURL];
204- if (requestDictionary == nil ) {
205- // If we're here, then we aren't currently fetching this image.
206- NSMutableDictionary *requestDictionary = [NSMutableDictionary dictionary ];
207- [_requests setObject: requestDictionary forKey: sourceImageURL];
203+ BOOL needsToFetch = NO ;
204+ @synchronized (_requests) {
205+ NSMutableDictionary *requestDictionary = [_requests objectForKey: sourceImageURL];
206+ if (requestDictionary == nil ) {
207+ // If we're here, then we aren't currently fetching this image.
208+ requestDictionary = [NSMutableDictionary dictionary ];
209+ [_requests setObject: requestDictionary forKey: sourceImageURL];
210+ needsToFetch = YES ;
211+ }
208212
209213 _FICAddCompletionBlockForEntity (formatName, requestDictionary, entity, completionBlock);
214+ }
215+
216+ if (needsToFetch) {
210217 UIImage *image;
211218 if ([entity respondsToSelector: @selector (imageForFormat: )]){
212219 FICImageFormat *format = [self formatWithName: formatName];
@@ -217,12 +224,9 @@ - (BOOL)_retrieveImageForEntity:(id <FICEntity>)entity withFormatName:(NSString
217224 [self _imageDidLoad: image forURL: sourceImageURL];
218225 } else if (_delegateImplementsWantsSourceImageForEntityWithFormatNameCompletionBlock){
219226 [_delegate imageCache: self wantsSourceImageForEntity: entity withFormatName: formatName completionBlock: ^(UIImage *sourceImage) {
220- [self _imageDidLoad: sourceImage forURL: sourceImageURL];
227+ [self _imageDidLoad: sourceImage forURL: sourceImageURL];
221228 }];
222229 }
223- } else {
224- // We have an existing request dictionary, which means this URL is currently being fetched.
225- _FICAddCompletionBlockForEntity (formatName, requestDictionary, entity, completionBlock);
226230 }
227231 } else {
228232 NSString *message = [NSString stringWithFormat: @" *** FIC Error: %s entity %@ returned a nil source image URL for image format %@ ." , __PRETTY_FUNCTION__, entity, formatName];
@@ -239,7 +243,13 @@ - (BOOL)_retrieveImageForEntity:(id <FICEntity>)entity withFormatName:(NSString
239243}
240244
241245- (void )_imageDidLoad : (UIImage *)image forURL : (NSURL *)URL {
242- NSDictionary *requestDictionary = [_requests objectForKey: URL];
246+ NSDictionary *requestDictionary;
247+ @synchronized (_requests) {
248+ requestDictionary = [_requests objectForKey: URL];
249+ [_requests removeObjectForKey: URL];
250+ // Now safe to use requestsDictionary outside the lock, because we've taken ownership from _requests
251+ }
252+
243253 if (requestDictionary != nil ) {
244254 for (NSMutableDictionary *entityDictionary in [requestDictionary allValues ]) {
245255 id <FICEntity> entity = [entityDictionary objectForKey: FICImageCacheEntityKey];
@@ -259,8 +269,6 @@ - (void)_imageDidLoad:(UIImage *)image forURL:(NSURL *)URL {
259269 }
260270 }
261271 }
262-
263- [_requests removeObjectForKey: URL];
264272}
265273
266274static void _FICAddCompletionBlockForEntity (NSString *formatName, NSMutableDictionary *entityRequestsDictionary, id <FICEntity> entity, FICImageCacheCompletionBlock completionBlock) {
@@ -435,27 +443,32 @@ - (void)deleteImageForEntity:(id <FICEntity>)entity withFormatName:(NSString *)f
435443
436444- (void )cancelImageRetrievalForEntity : (id <FICEntity>)entity withFormatName : (NSString *)formatName {
437445 NSURL *sourceImageURL = [entity sourceImageURLWithFormatName: formatName];
438- NSMutableDictionary *requestDictionary = [_requests objectForKey: sourceImageURL];
439- if (requestDictionary) {
440- NSString *entityUUID = [entity UUID ];
441- NSMutableDictionary *entityRequestsDictionary = [requestDictionary objectForKey: entityUUID];
442- if (entityRequestsDictionary) {
443- NSMutableDictionary *completionBlocksDictionary = [entityRequestsDictionary objectForKey: FICImageCacheCompletionBlocksKey];
444- [completionBlocksDictionary removeObjectForKey: formatName];
445-
446- if ([completionBlocksDictionary count ] == 0 ) {
447- [requestDictionary removeObjectForKey: entityUUID];
448- }
449-
450- if ([requestDictionary count ] == 0 ) {
451- [_requests removeObjectForKey: sourceImageURL];
452-
453- if (_delegateImplementsCancelImageLoadingForEntityWithFormatName) {
454- [_delegate imageCache: self cancelImageLoadingForEntity: entity withFormatName: formatName];
446+ NSString *entityUUID = [entity UUID ];
447+
448+ BOOL cancelImageLoadingForEntity = NO ;
449+ @synchronized (_requests) {
450+ NSMutableDictionary *requestDictionary = [_requests objectForKey: sourceImageURL];
451+ if (requestDictionary) {
452+ NSMutableDictionary *entityRequestsDictionary = [requestDictionary objectForKey: entityUUID];
453+ if (entityRequestsDictionary) {
454+ NSMutableDictionary *completionBlocksDictionary = [entityRequestsDictionary objectForKey: FICImageCacheCompletionBlocksKey];
455+ [completionBlocksDictionary removeObjectForKey: formatName];
456+
457+ if ([completionBlocksDictionary count ] == 0 ) {
458+ [requestDictionary removeObjectForKey: entityUUID];
459+ }
460+
461+ if ([requestDictionary count ] == 0 ) {
462+ [_requests removeObjectForKey: sourceImageURL];
463+ cancelImageLoadingForEntity = YES ;
455464 }
456465 }
457466 }
458467 }
468+
469+ if (cancelImageLoadingForEntity && _delegateImplementsCancelImageLoadingForEntityWithFormatName) {
470+ [_delegate imageCache: self cancelImageLoadingForEntity: entity withFormatName: formatName];
471+ }
459472}
460473
461474- (void )reset {
0 commit comments