0

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];
}

1 Answer 1

1

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];
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.