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

标签 ios cocoapods xcasset

简而言之:

如何从 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 是一个子模块,这个解决方案运行良好。然而,在检查我之前的 bundle 文件(与 main bundle 分开)时,我注意到所有图像都被简单地复制到 bundle... 即

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

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

Assets.car

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

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

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

Podspec syntax reference以此为例:

spec.resource = "Resources/HockeySDK.bundle"

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

不过,这与其说是解决方案,不如说是hack

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

最佳答案

我和你遇到了同样的情况,我最终采用了你提到的“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,这样 .bundle 就可用了,然后就可以链接了,就像你一直在源代码中一样。这样我就可以轻松地在 bundle 目标中添加新的资源/图像/xibs,它们将被编译和链接。就像一个魅力。

我在 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;
}

我还没有失败过。

关于ios - 如何在 NSBundle 中从 Assets.car(xcassets 的编译版本)加载图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21857986/

相关文章:

ios - 向 WKWebView 发送消息抛出错误

ios - 如何在 swift 中使用 CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer

ios - 错误 ITMS-90206 无效的包包含不允许的文件 'Frameworks'

ios - 本地 Pod 的 header 搜索路径

ios8 - 如何摆脱 Assets 目录编译器警告 "app icon is required for apps ... targeting iOS 7.0 ..."

ios - Admob 导致 Cocos2d 触摸延迟

iphone - 在 iOS 4.0 中使用 AVPlayer 进行 HTTP 直播?

ios - 由于 Xcode 错误导致的 pod 规范 lint 验证错误

ios - XCAssets 未复制到应用程序包

xcode - 有没有办法在Xcode 5或Xcode 6中更改xcassets View 的背景颜色?