英文:
Defining the type of a completionHandler in Objective-C
问题
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
@property (nonatomic, strong) NSDictionary<NSString *, NSMutableArray<void(^)(UIImage * _Nullable image)> *> *loadingResponses;
@end
-(void)fetchImage:(NSString *)urlString and:(void (^_Nonnull)(UIImage * _Nullable image))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 objectForKey:urlString] setArray:[[NSMutableArray alloc] initWithObjects:completionHandler, 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];
completionHandler(image);
NSArray *array = [self.loadingResponses objectForKey:urlString];
for (void(^responseCompletion)(UIImage * _Nullable image) in array) {
responseCompletion(image);
}
}
}] resume];
}
英文:
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
得分: 1
Your typedef
is fine as-is though I would name it ResponseBlock
, not responseBlock
.
typedef不需要修改,但我建议将其命名为ResponseBlock
,而不是responseBlock
。
When you use ResponseBlock
, don't use a pointer.
当你使用ResponseBlock
时,不要使用指针。
I also suggest changing loadingResponses
to be an NSMutableDictionary
so you can assign values to it.
我还建议将loadingResponses
更改为NSMutableDictionary
,以便你可以为其分配值。
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:
我假设你在某处初始化loadingResponses
如下:
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];
}
completionHandler(image);
NSArray<ResponseBlock> *array = self.loadingResponses[urlString];
for (ResponseBlock 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];
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论