I can't manage to get the responseCompletion
type correct, at the for cycle.
Tried to replace it with typedef, but got no luck, only more errors.
@interface ImageManager : NSObject
//typedef void(^responseBlock)(UIImage * _Nullable image);
@property (nonatomic, strong) NSDictionary<NSString *,NSMutableArray<void(^)(UIImage * _Nullable image)> *> *loadingResponses;
@end
-(void)fetchImage:(NSString *)urlString and:(void (^_Nonnull)(UIImage * _Nullable image))completionhHandler {
UIImage *image = [self.cache objectForKey:urlString];
if (image != nil) {
completionhHandler(image);
return;
}
if (self.loadingResponses[urlString] != nil) {
[self.loadingResponses[urlString] addObject:completionhHandler];
return;
} else {
[[self.loadingResponses objectForKey:urlString] setArray:[[NSMutableArray alloc] initWithObjects:completionhHandler, nil]];
}
NSURL *url = [[NSURL alloc] initWithString:urlString];
[[self.session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error != nil) {
UIImage *image = [[UIImage alloc] initWithData:data];
[self.cache setObject:image forKey:urlString];
completionhHandler(image);
NSArray *array = [self.loadingResponses objectForKey:urlString];
for ((void(^)(UIImage * _Nullable image) *responseCompletion) in array) {
responseCompletion(image);
}
}
}] resume];
}
Your typedef
is fine as-is though I would name it ResponseBlock
, not responseBlock
.
typedef void(^ResponseBlock)(UIImage * _Nullable image);
When you use ResponseBlock
, don't use a pointer.
I also suggest changing loadingResponses
to be an NSMutableDictionary
so you can assign values to it.
Here's an updated version of your code:
The interface:
typedef void(^ResponseBlock)(UIImage * _Nullable image);
@interface ImageManager : NSObject
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSMutableArray<ResponseBlock> *> *loadingResponses;
@end
The method:
- (void)fetchImage:(NSString *)urlString and:(ResponseBlock)completionHandler {
UIImage *image = [self.cache objectForKey:urlString];
if (image != nil) {
completionHandler(image);
return;
}
if (self.loadingResponses[urlString] != nil) {
[self.loadingResponses[urlString] addObject:completionHandler];
return;
} else {
self.loadingResponses[urlString] = [NSMutableArray arrayWithObject:completionHandler];
}
NSURL *url = [[NSURL alloc] initWithString:urlString];
[[self.session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error != nil) {
UIImage *image = [[UIImage alloc] initWithData:data];
[self.cache setObject:image forKey:urlString];
completionHandler(image);
NSArray *array = [self.loadingResponses objectForKey:urlString];
for (ResponseBlock responseCompletion in array) {
responseCompletion(image);
}
}
}] resume];
}
I'm assuming somewhere you initialize loadingResponses
as:
self.loadingResponses = [NSMutableDictionary dictionary];
You also need to call the completion handler if there is an error. Perhaps you mean to do:
[[self.session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
UIImage *image = nil;
if (error != nil) {
image = [[UIImage alloc] initWithData:data];
[self.cache setObject:image forKey:urlString];
}
completionhHandler(image);
NSArray<ResponseBlock> *array = self.loadingResponses[urlString];
for (ResponseBlock responseCompletion in array) {
responseCompletion(image);
}
}] resume];