Support bundle argument for image loading

Reviewed By: mmmulani

Differential Revision: D3768798

fbshipit-source-id: 5b35f06957cebfe74aca90fe6a456f7f739509a9
This commit is contained in:
Pieter De Baets 2016-08-31 17:30:50 -07:00 committed by Facebook Github Bot 3
parent 74308209f9
commit 46b54fd7a8
14 changed files with 286 additions and 7 deletions

View File

@ -58,8 +58,11 @@
27B885561BED29AF00008352 /* RCTRootViewIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B885551BED29AF00008352 /* RCTRootViewIntegrationTests.m */; };
27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; };
3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; };
3D13F8481D6F6AF900E69E0E /* ImageInBundle.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D13F8441D6F6AF200E69E0E /* ImageInBundle.png */; };
3D13F84A1D6F6AFD00E69E0E /* OtherImages.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3D13F8451D6F6AF200E69E0E /* OtherImages.xcassets */; };
3D299BAF1D33EBFA00FA1057 /* RCTLoggingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D299BAE1D33EBFA00FA1057 /* RCTLoggingTests.m */; };
3D2AFAF51D646CF80089D1A3 /* LegacyImage@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* LegacyImage@2x.png */; };
3D56F9F11D6F6E9B00F53A06 /* UIExplorerBundle.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3D13F83E1D6F6AE000E69E0E /* UIExplorerBundle.bundle */; };
3DB99D0C1BA0340600302749 /* UIExplorerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DB99D0B1BA0340600302749 /* UIExplorerIntegrationTests.m */; };
3DD981D61D33C6FB007DC7BE /* TestBundle.js in Resources */ = {isa = PBXBuildFile; fileRef = 3DD981D51D33C6FB007DC7BE /* TestBundle.js */; };
68FF44381CF6111500720EFD /* RCTBundleURLProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FF44371CF6111500720EFD /* RCTBundleURLProviderTests.m */; };
@ -162,6 +165,13 @@
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTLinking;
};
3D13F84B1D6F6B5F00E69E0E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 3D13F83D1D6F6AE000E69E0E;
remoteInfo = UIExplorerBundle;
};
58005BED1ABA80530062E044 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 58005BE41ABA80530062E044 /* RCTTest.xcodeproj */;
@ -243,6 +253,10 @@
27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlexibleSizeExampleView.m; path = UIExplorer/NativeExampleViews/FlexibleSizeExampleView.m; sourceTree = "<group>"; };
27F441EA1BEBE5030039B79C /* FlexibleSizeExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlexibleSizeExampleView.h; path = UIExplorer/NativeExampleViews/FlexibleSizeExampleView.h; sourceTree = "<group>"; };
357858F81B28D2C400341EDB /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
3D13F83E1D6F6AE000E69E0E /* UIExplorerBundle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerBundle.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
3D13F8401D6F6AE000E69E0E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Info.plist; sourceTree = "<group>"; };
3D13F8441D6F6AF200E69E0E /* ImageInBundle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ImageInBundle.png; sourceTree = "<group>"; };
3D13F8451D6F6AF200E69E0E /* OtherImages.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = OtherImages.xcassets; sourceTree = "<group>"; };
3D299BAE1D33EBFA00FA1057 /* RCTLoggingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLoggingTests.m; sourceTree = "<group>"; };
3D2AFAF41D646CF80089D1A3 /* LegacyImage@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "LegacyImage@2x.png"; path = "UIExplorer/LegacyImage@2x.png"; sourceTree = "<group>"; };
3DB99D0B1BA0340600302749 /* UIExplorerIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExplorerIntegrationTests.m; sourceTree = "<group>"; };
@ -306,6 +320,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
3D13F83B1D6F6AE000E69E0E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@ -537,6 +558,17 @@
name = Products;
sourceTree = "<group>";
};
3D13F83F1D6F6AE000E69E0E /* UIExplorerBundle */ = {
isa = PBXGroup;
children = (
3D13F8401D6F6AE000E69E0E /* Info.plist */,
3D13F8441D6F6AF200E69E0E /* ImageInBundle.png */,
3D13F8451D6F6AF200E69E0E /* OtherImages.xcassets */,
);
name = UIExplorerBundle;
path = UIExplorer/UIExplorerBundle;
sourceTree = "<group>";
};
58005BE51ABA80530062E044 /* Products */ = {
isa = PBXGroup;
children = (
@ -560,6 +592,7 @@
1316A21D1AA397F400C0188E /* Libraries */,
143BC57C1B21E18100462512 /* UIExplorerUnitTests */,
143BC5961B21E3E100462512 /* UIExplorerIntegrationTests */,
3D13F83F1D6F6AE000E69E0E /* UIExplorerBundle */,
14D6D6EA1B2205C0001FB087 /* OCMock */,
83CBBA001A601CBA00E9B192 /* Products */,
);
@ -573,6 +606,7 @@
13B07F961A680F5B00A75B9A /* UIExplorer.app */,
004D289E1AAF61C70097A701 /* UIExplorerUnitTests.xctest */,
143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */,
3D13F83E1D6F6AE000E69E0E /* UIExplorerBundle.bundle */,
);
name = Products;
sourceTree = "<group>";
@ -617,6 +651,7 @@
buildRules = (
);
dependencies = (
3D13F84C1D6F6B5F00E69E0E /* PBXTargetDependency */,
);
name = UIExplorer;
productName = "Hello World";
@ -641,6 +676,23 @@
productReference = 143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
3D13F83D1D6F6AE000E69E0E /* UIExplorerBundle */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3D13F8411D6F6AE000E69E0E /* Build configuration list for PBXNativeTarget "UIExplorerBundle" */;
buildPhases = (
3D13F83A1D6F6AE000E69E0E /* Sources */,
3D13F83B1D6F6AE000E69E0E /* Frameworks */,
3D13F83C1D6F6AE000E69E0E /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = UIExplorerBundle;
productName = UIExplorerBundle;
productReference = 3D13F83E1D6F6AE000E69E0E /* UIExplorerBundle.bundle */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@ -657,6 +709,9 @@
CreatedOnToolsVersion = 6.3.2;
TestTargetID = 13B07F861A680F5B00A75B9A;
};
3D13F83D1D6F6AE000E69E0E = {
CreatedOnToolsVersion = 7.3.1;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "UIExplorer" */;
@ -737,6 +792,7 @@
13B07F861A680F5B00A75B9A /* UIExplorer */,
004D289D1AAF61C70097A701 /* UIExplorerUnitTests */,
143BC5941B21E3E100462512 /* UIExplorerIntegrationTests */,
3D13F83D1D6F6AE000E69E0E /* UIExplorerBundle */,
);
};
/* End PBXProject section */
@ -863,6 +919,7 @@
buildActionMask = 2147483647;
files = (
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
3D56F9F11D6F6E9B00F53A06 /* UIExplorerBundle.bundle in Resources */,
3D2AFAF51D646CF80089D1A3 /* LegacyImage@2x.png in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
);
@ -875,6 +932,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
3D13F83C1D6F6AE000E69E0E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3D13F8481D6F6AF900E69E0E /* ImageInBundle.png in Resources */,
3D13F84A1D6F6AFD00E69E0E /* OtherImages.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@ -945,6 +1011,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
3D13F83A1D6F6AE000E69E0E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@ -953,6 +1026,11 @@
target = 13B07F861A680F5B00A75B9A /* UIExplorer */;
targetProxy = 143BC59B1B21E3E100462512 /* PBXContainerItemProxy */;
};
3D13F84C1D6F6B5F00E69E0E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 3D13F83D1D6F6AE000E69E0E /* UIExplorerBundle */;
targetProxy = 3D13F84B1D6F6B5F00E69E0E /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@ -1083,6 +1161,34 @@
};
name = Release;
};
3D13F8421D6F6AE000E69E0E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
COMBINE_HIDPI_IMAGES = YES;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = UIExplorer/UIExplorerBundle/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.UIExplorerBundle;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
WRAPPER_EXTENSION = bundle;
};
name = Debug;
};
3D13F8431D6F6AE000E69E0E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
COMBINE_HIDPI_IMAGES = YES;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = UIExplorer/UIExplorerBundle/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.UIExplorerBundle;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
WRAPPER_EXTENSION = bundle;
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1250,6 +1356,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3D13F8411D6F6AE000E69E0E /* Build configuration list for PBXNativeTarget "UIExplorerBundle" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3D13F8421D6F6AE000E69E0E /* Debug */,
3D13F8431D6F6AE000E69E0E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "UIExplorer" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -6,6 +6,20 @@
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3D13F83D1D6F6AE000E69E0E"
BuildableName = "UIExplorerBundle.bundle"
BlueprintName = "UIExplorerBundle"
ReferencedContainer = "container:UIExplorer.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 Facebook. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "react-logo.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -613,11 +613,39 @@ exports.examples = [
return (
<Image
source={require('image!LegacyImage')}
style={styles.base}
/>
);
},
},
{
title: 'Bundled images',
description:
'Images shipped in a separate native bundle',
render: function() {
return (
<View style={{flexDirection: 'row'}}>
<Image
source={{
url: 'ImageInBundle',
bundle: 'UIExplorerBundle',
width: 100,
height: 100,
}}
style={{borderColor: 'yellow', borderWidth: 4}}
/>
<Image
source={{
url: 'ImageInAssetCatalog',
bundle: 'UIExplorerBundle',
width: 100,
height: 100,
}}
style={{marginLeft: 10, borderColor: 'blue', borderWidth: 4}}
/>
</View>
);
},
},
];
var fullImage = {uri: 'http://facebook.github.io/react/img/logo_og.png'};

View File

@ -21,6 +21,12 @@ const ImageURISourcePropType = PropTypes.shape({
* function).
*/
uri: PropTypes.string,
/**
* `bundle` is the iOS asset bundle which the image is included in. This
* will default to [NSBundle mainBundle] if not set.
* @platform ios
*/
bundle: PropTypes.string,
/**
* `method` is the HTTP Method to use. Defaults to GET if not specified.
*/

View File

@ -36,6 +36,36 @@ RCT_EXPORT_MODULE()
return NO;
}
static NSString *bundleName(NSBundle *bundle)
{
NSString *name = bundle.infoDictionary[@"CFBundleName"];
if (!name) {
name = [[bundle.bundlePath lastPathComponent] stringByDeletingPathExtension];
}
return name;
}
static NSBundle *bundleForPath(NSString *key)
{
static NSMutableDictionary *bundleCache;
if (!bundleCache) {
bundleCache = [NSMutableDictionary new];
bundleCache[@"main"] = [NSBundle mainBundle];
// Initialize every bundle in the array
for (NSString *path in [[NSBundle mainBundle] pathsForResourcesOfType:@"bundle" inDirectory:nil]) {
[NSBundle bundleWithPath:path];
}
// The bundles initialized above will now also be in `allBundles`
for (NSBundle *bundle in [NSBundle allBundles]) {
bundleCache[bundleName(bundle)] = bundle;
}
}
return bundleCache[key];
}
- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL
size:(CGSize)size
scale:(CGFloat)scale
@ -50,7 +80,23 @@ RCT_EXPORT_MODULE()
}
NSString *imageName = RCTBundlePathForURL(imageURL);
UIImage *image = [UIImage imageNamed:imageName];
NSBundle *bundle;
NSArray *imagePathComponents = [imageName pathComponents];
if ([imagePathComponents count] > 1 &&
[[[imagePathComponents firstObject] pathExtension] isEqualToString:@"bundle"]) {
NSString *bundlePath = [imagePathComponents firstObject];
bundle = bundleForPath([bundlePath stringByDeletingPathExtension]);
imageName = [imageName substringFromIndex:(bundlePath.length + 1)];
}
UIImage *image;
if (bundle) {
image = [UIImage imageNamed:imageName inBundle:bundle compatibleWithTraitCollection:nil];
} else {
image = [UIImage imageNamed:imageName];
}
if (image) {
if (progressHandler) {
progressHandler(1, 1);

View File

@ -34,7 +34,7 @@ RCT_EXPORT_MODULE()
}
- (NSOperation *)sendRequest:(NSURLRequest *)request
withDelegate:(id<RCTURLRequestDelegate>)delegate
withDelegate:(id<RCTURLRequestDelegate>)delegate
{
// Lazy setup
if (!_fileQueue) {

View File

@ -125,10 +125,19 @@ RCT_CUSTOM_CONVERTER(NSData *, NSData, [json dataUsingEncoding:NSUTF8StringEncod
return URL ? [NSURLRequest requestWithURL:URL] : nil;
}
if ([json isKindOfClass:[NSDictionary class]]) {
NSURL *URL = [self NSURL:json[@"uri"] ?: json[@"url"]];
NSString *URLString = json[@"uri"] ?: json[@"url"];
NSURL *URL;
NSString *bundleName = json[@"bundle"];
if (bundleName) {
URLString = [NSString stringWithFormat:@"%@.bundle/%@", bundleName, URLString];
}
URL = [self NSURL:URLString];
if (!URL) {
return nil;
}
NSData *body = [self NSData:json[@"body"]];
NSString *method = [self NSString:json[@"method"]].uppercaseString ?: @"GET";
NSDictionary *headers = [self NSDictionary:json[@"headers"]];

View File

@ -46,6 +46,12 @@
(CGSizeEqualToSize(_size, object.size) || CGSizeEqualToSize(object.size, CGSizeZero));
}
- (NSString *)description
{
return [NSString stringWithFormat:@"<RCTImageSource: %p URL=%@, size=%@, scale=%0.f>",
self, _request.URL, NSStringFromCGSize(_size), _scale];
}
@end
@implementation RCTConvert (ImageSource)
@ -75,8 +81,8 @@
}
RCTImageSource *imageSource = [[RCTImageSource alloc] initWithURLRequest:request
size:size
scale:scale];
size:size
scale:scale];
imageSource.packagerAsset = packagerAsset;
return imageSource;
}

View File

@ -594,7 +594,7 @@ NSData *__nullable RCTGzipData(NSData *__nullable input, float level)
return output;
}
NSString *__nullable RCTBundlePathForURL(NSURL *__nullable URL)
NSString *__nullable RCTBundlePathForURL(NSURL *__nullable URL)
{
if (!URL.fileURL) {
// Not a file path