I’ve had a very rarely occurring bug where a key in an NSMutableDictionary instance ends up pointing to the wrong object (another object in the same dictionary).
Could “key confusion” be the result of a race condition?
Here’s the code (I’ve put in new thread safety since):
- (NSNumber*) makeHashFromResizedImage:(UIImage*)original newSize:(CGSize)newSize {
int retVal = original.hash + newSize.width * 2 + newSize.height * 4;
return [NSNumber numberWithInteger:retVal];
}
- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
NSNumber *key = [self makeHashFromResizedImage:image newSize:newSize];
if ([self.resizedImages objectForKey:key]) {
return [self.resizedImages objectForKey:key];
}
UIImage *newImage = {{image-resizing-code-here}};
[self.resizedImages setObject:newImage forKey:key];
return newImage;
}
Note: {{image-resizing-code-here}} was removed for brevity. I’m beginning to suspect my makeHashFromResizedImage as it probably doesn’t work as expected. Going to Unit Test it now.
This:
If another thread called
setObject:forKey:with thatkeythe result of the 2nd line will be different from the first line. Why not just store it in a variable? At least the thing you check and the thing you return will be the same.(The
retain+autoreleaseis just to retainimagewon’t be-dealloc-ed when this thread is running.)If you have to ensure that the
keycorresponding to thatimagewill not be overwritten before the function returns, you’ll need to use a lock, as others answered.Edit: Perhaps you should use an NSMutableSet of the UIImage instead. Especially, don’t use a hash value as a key! A hash value does not need to be different when the two objects are not the same. Create a new class X which contains a CGSize and UIImage property, and use a NSMutableSet of X, if the same UIImage can be added multiple times.