【问题标题】:How can I load an image from Assets.car (compiled version of xcassets) within an NSBundle?如何从 NSBundle 中的 Assets.car(xcassets 的编译版本)加载图像?
【发布时间】:2014-03-18 10:55:36
【问题描述】:

简而言之:

如何从 NSBundle 中的已编译 Assets.car 加载图像?

完整版:

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

Core 包括代码文件、xib 文件和几个xcasset 文件。

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

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

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

但是,Core 中的任何xcasset 文件中没有个图像显示。

我(天真地)尝试使用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

以前,Core 是 submodule,这个解决方案运行良好。然而,在检查我之前的bundle 文件(与main 捆绑包分开)后,我注意到所有图像都被简单地复制到bundle... 即

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

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

Assets.car

据我了解,它是上述Core 子目录中的xcasset 文件所有的组合编译版本。

如何在这个Core 资源包中从这个编译的Assets.car 加载图像?

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

Podspec syntax reference 举个例子:

spec.resource = "Resources/HockeySDK.bundle"

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

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

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

【问题讨论】:

    标签: ios cocoapods xcasset


    【解决方案1】:

    我的情况和你一样,我最终选择了你提到的“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 install 之前构建捆绑包,以便 .bundle 可用,然后就可以像在源代码中一样链接它。这样我就可以轻松地在捆绑目标中添加新的资源/图像/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;
    }
    

    我还没有失败过。

    【讨论】:

    • +1:是的,我做了非常相似的事情。实际上,您可以让 CocoaPods 完全为您创建资源包——无需预安装钩子。我会尽快把它写成另一种可能的解决方案。
    • @JRG-Developer 太棒了,很想看看。
    • 希望看到现代非黑客版本
    • @FullDecent 我的最新版本不再使用预安装步骤,并且在 s.resource_bundle 配置中有一个小的变化。其余的保持不变。
    猜你喜欢
    • 2014-05-17
    • 1970-01-01
    • 2017-10-08
    • 2021-08-29
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    相关资源
    最近更新 更多