无法将UIImage存入NSMutableDictionary:Parse服务器图片存储失败
看起来你遇到的问题是把从Parse获取的图片存入NSMutableDictionary后无法读取,虽然storedImage不为空,但字典里就是找不到对应的对象。我帮你梳理几个可能的原因和对应的修复方案:
1. 线程安全问题(最可能的原因)
getDataInBackgroundWithBlock:的回调block是在后台线程执行的,而NSMutableDictionary本身不是线程安全的。跨线程修改字典会导致数据竞争,可能出现对象看似存入但实际未被正确写入,或者读取时数据不一致的情况。另外,[self.collectionView reloadData]是UI操作,必须在主线程执行,你直接在后台线程调用也会有问题。
修复方式:
把字典操作和UI刷新逻辑切换到主线程执行:
NSString* messageSenderId = [receivedMessage objectForKey:@"Sender Id"]; NSLog(@"messageSenderId = %@", messageSenderId); if([self.avatarDictionary objectForKey:messageSenderId] == nil) { PFQuery* userQuery = [PFUser query]; [userQuery whereKey:@"objectId" equalTo:messageSenderId]; // 修正变量名错误:把messageSenderQuery改为userQuery PFUser* messageSender = (PFUser *)[[userQuery findObjects] firstObject]; if (messageSender) { // 增加判空,避免空指针 PFFile *avatarImage = messageSender[@"profilePictureSmall"]; [avatarImage getDataInBackgroundWithBlock:^(NSData * _Nullable data, NSError * _Nullable error) { if (!error && data) { UIImage* storedImage = [UIImage imageWithData:data]; // 切换到主线程操作字典和刷新UI dispatch_async(dispatch_get_main_queue(), ^{ // 统一使用messageSenderId作为键,避免键不匹配 [self.avatarDictionary setObject:storedImage forKey:messageSenderId]; NSLog(@"objectForKey: %@", [self.avatarDictionary objectForKey:messageSenderId]); [self.collectionView reloadData]; }); } else { NSLog(@"获取头像数据失败:%@", error?.localizedDescription ?? "未知错误"); } }]; } }
2. 键不匹配问题
你一开始用messageSenderId检查字典是否存在对应值,但存储时用的是messageSender.objectId。虽然理论上这两个值应该相同,但如果receivedMessage里的Sender Id字段和Parse用户的objectId存在差异(比如大小写、空格或者字段名错误),就会导致存储的键和查询的键不一致,自然读不到数据。
修复方式:
统一使用同一个键,比如全程用messageSenderId(你已经从receivedMessage里拿到的那个值),避免不必要的变量差异。
3. 变量名笔误
原代码中定义的查询对象是userQuery,但调用findObjects时写成了messageSenderQuery,这会导致编译错误或者运行时无法获取到用户对象。虽然你说storedImage不为空,可能是输入时的笔误,但还是要确认实际代码里的变量名是否一致。
额外建议
- 给
self.avatarDictionary加线程保护:如果你的代码中有其他线程也会操作这个字典,建议用@synchronized或者NSLock来保证线程安全,避免后续再出现类似问题。 - 增加错误处理:在获取Parse数据和图片数据的环节都加上错误判断,方便排查问题。
内容的提问来源于stack exchange,提问作者Sam

