Removed all calls to [UIImage imageWithData:] on a background thread

Summary: public

I had previously assumed (based on past experience and common wisdom) that `[UIImage imageWithData:]` was safe to call concurrently and/or off the main thread, but it seems that may not be the case (see https://github.com/AFNetworking/AFNetworking/pull/2815).

This diff replaces `[UIImage imageWithData:]` with ImageIO-based decoding wherever possible, and ensures that it is called on the main thread wherever that's not possible/convenient.

I've also serialized access to the `NSURLCache` inside `RCTImageLoader`, which was causing a separate-but-similar crash when loading images.

Reviewed By: fkgozali

Differential Revision: D2678369

fb-gh-sync-id: 74d033dafcf6c412556e4c96f5ac5d3432298b18
This commit is contained in:
Nick Lockwood
2015-11-20 05:15:49 -08:00
committed by facebook-github-bot-6
parent 1a1c3f76a2
commit 0fe074acbd
4 changed files with 137 additions and 105 deletions

View File

@@ -429,7 +429,18 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[
return nil;
}
UIImage *image;
__block UIImage *image;
if (![NSThread isMainThread]) {
// It seems that none of the UIImage loading methods can be guaranteed
// thread safe, so we'll pick the lesser of two evils here and block rather
// than run the risk of crashing
RCTLogWarn(@"Calling [RCTConvert UIImage:] on a background thread is not recommended");
dispatch_sync(dispatch_get_main_queue(), ^{
image = [self UIImage:json];
});
return image;
}
NSString *path;
CGFloat scale = 0.0;
BOOL isPackagerAsset = NO;
@@ -452,7 +463,6 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[
if (RCTIsXCAssetURL(URL)) {
// Image may reside inside a .car file, in which case we have no choice
// but to use +[UIImage imageNamed] - but this method isn't thread safe
RCTAssertMainThread();
NSString *assetName = RCTBundlePathForURL(URL);
image = [UIImage imageNamed:assetName];
} else {