Objective-C中for循环内responseCompletion的类型定义问题
问题解决与代码修正
核心问题分析
- Block类型声明错误:for-in循环中直接内联声明block类型的写法不符合Objective-C语法规范,需通过typedef简化后使用。
- 容器类型不匹配:
loadingResponses声明为不可变NSDictionary,但后续要修改其中的数组,应使用NSMutableDictionary。 - 逻辑错误:网络请求的错误判断写反,
error != nil时应处理错误而非加载图片;同时存在拼写错误completionhHandler。 - 数组初始化错误:字典中不存在对应key时,直接调用
setArray会导致空指针崩溃,需先创建可变数组并存入字典。
修正后的完整代码
@interface ImageManager : NSObject // 提前定义block类型,简化后续使用 typedef void(^ImageResponseBlock)(UIImage * _Nullable image); // 改为NSMutableDictionary,支持动态修改内容 @property (nonatomic, strong) NSMutableDictionary<NSString *, NSMutableArray<ImageResponseBlock> *> *loadingResponses; @property (nonatomic, strong) NSCache *cache; @property (nonatomic, strong) NSURLSession *session; @end @implementation ImageManager - (instancetype)init { self = [super init]; if (self) { _cache = [[NSCache alloc] init]; _session = [NSURLSession sharedSession]; _loadingResponses = [[NSMutableDictionary alloc] init]; } return self; } -(void)fetchImage:(NSString *)urlString and:(ImageResponseBlock _Nonnull)completionHandler { // 修正拼写错误:completionhHandler -> completionHandler UIImage *image = [self.cache objectForKey:urlString]; if (image != nil) { completionHandler(image); return; } NSMutableArray<ImageResponseBlock> *responseBlocks = self.loadingResponses[urlString]; if (responseBlocks != nil) { [responseBlocks addObject:completionHandler]; return; } else { // 先创建可变数组,再存入字典避免空指针 responseBlocks = [[NSMutableArray alloc] initWithObjects:completionHandler, nil]; self.loadingResponses[urlString] = responseBlocks; } NSURL *url = [[NSURL alloc] initWithString:urlString]; [[self.session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { UIImage *fetchedImage = nil; if (error == nil) { // 修正错误判断:无错误时才处理图片 fetchedImage = [[UIImage alloc] initWithData:data]; if (fetchedImage) { [self.cache setObject:fetchedImage forKey:urlString]; } } // 遍历调用所有回调 NSMutableArray<ImageResponseBlock> *blocks = self.loadingResponses[urlString]; for (ImageResponseBlock responseCompletion in blocks) { responseCompletion(fetchedImage); } // 执行完回调后移除对应key,避免重复触发 [self.loadingResponses removeObjectForKey:urlString]; completionHandler(fetchedImage); }] resume]; } @end
关键修正点说明
- typedef的正确使用:提前定义
ImageResponseBlock类型,后续所有需要用到该block的地方直接使用类型名,既避免重复复杂声明,也解决了for循环中的类型匹配问题。 - 容器类型修正:将
loadingResponses改为NSMutableDictionary,确保可以动态添加/修改其中的数组;数组初始化时先创建再存入字典,避免空指针崩溃。 - 逻辑修复:修正网络请求的错误判断逻辑,确保只有请求成功时才加载图片;执行完所有回调后移除字典中的对应key,防止重复触发回调。
- 拼写修正:将
completionhHandler改为正确的completionHandler,避免编译错误。
内容的提问来源于stack exchange,提问作者bruno
相关产品推荐
相关产品推荐

