如何从NSBundle中的Assets.car(xcassets的编译版本)加载图像?

时间:2014-02-18 15:21:46

标签: ios cocoapods xcasset

简而言之:

如何从Assets.car内的已编译NSBundle加载图片?

完整版:

我正在将一套应用转换为使用CocoaPods。每个应用都依赖于名为Core的共享广告连播。

Core包含代码文件,xib文件和多个xcasset文件。

以下是创建资源包的Podspec Core的相关行:

  s.resource_bundles = {'CoreResources' => ['Core/Resources/*']}

Podspec传递pod spec lint,依赖于它的主项目正确构建。

但是,xcassetCore个文件中的图像的正在显示。

我(天真)尝试使用UIImage上的类别加载图片,如下所示:

@implementation UIImage (Bundle)

+ (UIImage *)imageNamed:(NSString *)name bundle:(NSBundle *)bundle
{
    if (!bundle)
        return [UIImage imageNamed:name];

    UIImage *image = [UIImage imageNamed:[self imageName:name forBundle:bundle]];
    return image;
}

+ (NSString *)imageName:(NSString *)name forBundle:(NSBundle *)bundle
{
    NSString *bundleName = [[bundle bundlePath] lastPathComponent];
    name = [bundleName stringByAppendingPathComponent:name];
    return name;
}
@end

以前,Coresubmodule,此解决方案运行正常。但是,在检查我之前的bundle文件(与main捆绑包分开)后,我发现所有图片都被简单地复制到了bundle ...即

Image.pngImage@2x.png等都在捆绑中。

检查CocoaPods生成的包时,它包含

Assets.car

我理解为所有<{1}}子目录中所有 xcasset个文件的组合编译版本。

如何在此Core资源包中加载此已​​编译Assets.car的图片?

作为一个黑客,我想我可以......

Podspec syntax reference以此为例:

Core

这似乎表明可以在Xcode中手动创建捆绑包并让CocoaPods简单地复制它。

这更像是一个 hack 而非解决方案。

我相信CocoaPods(v 0.29+)可以完全处理这个......?

1 个答案:

答案 0 :(得分:4)

我和你一样处于同样的境地,我最终选择了你提到的“hack”,但是在pod安装过程中它是自动化的,所以它更易于维护。

在我的podspec中我有

# Pre-build resource bundle so it can be copied later
  s.pre_install do |pod, target_definition|
    Dir.chdir(pod.root) do
      command = "xcodebuild -project MyProject.xcodeproj -target MyProjectBundle CONFIGURATION_BUILD_DIR=Resources 2>&1 > /dev/null"
      unless system(command)
        raise ::Pod::Informative, "Failed to generate MyProject resources bundle"
      end
    end
  end

然后在podspec:

  s.resource = 'Resources/MyProjectBundle.bundle'

这里的技巧是在pod安装之前构建软件包,以便.bundle可用,然后就可以像在源代码中一样将它链接起来。这样我就可以轻松地在bundle目标中添加新的资源/ images / xib,并且它们将被编译和链接。像魅力一样。

我在NSBundle + MyResources上有一个类别,可以轻松访问捆绑资源:

+ (NSBundle *)myProjectResources
{
    static dispatch_once_t onceToken;
    static NSBundle *bundle = nil;
    dispatch_once(&onceToken, ^{
        // This bundle name must be the same as the product name for the resources bundle target
        NSURL *url = [[NSBundle bundleForClass:[SomeClassInMyProject class]] URLForResource:@"MyProject" withExtension:@"bundle"];
        if (!url) {
            url = [[NSBundle mainBundle] URLForResource:@"MyProject" withExtension:@"bundle"];
        }
        bundle = [NSBundle bundleWithURL:url];
    });
    return bundle;
}

因此,如果你想加载,例如核心数据模型:

NSURL *modelURL = [[NSBundle myProjectResources] URLForResource:@"MyModel" withExtension:@"momd"];

我也有一些方便的方法来访问图像:

+ (UIImage *)bundleImageNamed:(NSString *)name
{
    UIImage *imageFromMainBundle = [UIImage imageNamed:name];
    if (imageFromMainBundle) {
        return imageFromMainBundle;
    }

    NSString *imageName = [NSString stringWithFormat:@"MyProject.bundle/%@", name];
    UIImage *imageFromBundle = [UIImage imageNamed:imageName];
    if (!imageFromBundle) {
        NSLog(@"Image not found: %@", name);
    }
    return imageFromBundle;
}

我还没有失败。