如何从NSBundle中的Assets.car(xcassets的编译版本)加载图像? [英] How can I load an image from Assets.car (compiled version of xcassets) within an NSBundle?

查看:182
本文介绍了如何从NSBundle中的Assets.car(xcassets的编译版本)加载图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之:

如何从已编译的 Assets.car NSBundle 中?

完整版本:

我正在将一套应用程序转换为使用 CocoaPods 。每个应用程序都依赖于一个名为 Core 的共享pod。

I'm in the process of converting a suite of apps to use CocoaPods. Each app relies on a shared pod called Core.

Core 包括代码文件, xib 文件,以及几个 xcasset 文件。

Core includes code files, xib files, and several xcasset files.

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

Here's the relevant line from the Podspec for Core that creates the resource bundle:

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

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

The Podspec passes pod spec lint, and main project that relies on it correctly builds.

然而,<来自核心内的任何 xcasset 文件中的图像的em> none 正在显示。

However, none of the images from any xcasset files within Core are showing.

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

I am (naively) trying to load the images using a category on UIImage like this:

@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

以前,核心是一个子模块,这个解决方案运行正常。但是,在检查我以前的捆绑文件(与 main 捆绑包分开)时,我注意到所有图像都是只需复制到 ...即

Previously, Core was a submodule, and this solution worked fine. However, upon inspection of my previous bundle file (separate from main bundle), I noticed that all of the images were simply being copied into the bundle... i.e.

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

检查后 CocoaPods - 生成的包,它包含

Upon inspection of the CocoaPods-generated bundle, it contains an

Assets.car

我理解为所有 xcasset 所述 Core 子目录中的文件。

which I understand to be a combined, compiled version of all the xcasset files within said Core subdirectory.

如何从此编译的资产中加载图像.car 在这个核心资源包中?

How can I load images from this compiled Assets.car within this Core resources bundle?

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

Podspec语法参考以此为例:

spec.resource = "Resources/HockeySDK.bundle"

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

This seems to suggest that it's possible to create the bundle manually within Xcode and have CocoaPods simply copy it.

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

This is more of a hack than a solution, though.

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

I believe CocoaPods (v 0.29+) can handle this entirely...?

推荐答案

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

I was in the same situation as you, and I ended up going with the "hack" you mentioned, but it is automated during pod install so it's a lot more maintainable.

在我的podspec中我有

In my podspec I have

# 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中:

Then later on in the podspec:

  s.resource = 'Resources/MyProjectBundle.bundle'

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

The trick here is to build the bundle before pod install so that the .bundle is available, and can then just be linked as if you had it in the source all along. That way I can easily added new resources/images/xibs in the bundle target, and they will be compiled and linked. Works like a charm.

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

The I have a category on NSBundle+MyResources that allows easy access to the bundle resources:

+ (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;
}

所以如果你想加载例如核心数据模型:

So if you want to load e.g. a core data model:

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

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

I've made some convenience methods to access images as well:

+ (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;
}

我还没有失败。

这篇关于如何从NSBundle中的Assets.car(xcassets的编译版本)加载图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆