如何在 cocoapods 中加载资源 resource_bundle

How to load resource in cocoapods resource_bundle

我为如何在 cocoapods 中加载资源而苦苦挣扎 resource_bundle。

以下是我放入 .podspecs 文件中的内容。

s.source_files = 'XDCoreLib/Pod/Classes/**/*'
s.resource_bundles = {
'XDCoreLib' => ['XDCoreLib/Pod/Resources/**/*.{png,storyboard}']
}

这就是我在主项目中尝试做的事情。

let bundle = NSBundle(forClass: XDWebViewController.self)
let image = UIImage(named: "ic_arrow_back", inBundle: bundle, compatibleWithTraitCollection: nil)
print(image)

我确实在 XDCoreLib.bundle 中看到了图片,但是 return 没有。

我在类似的问题上苦苦挣扎了一段时间。 pod 的资源包实际上是与您的代码所在位置不同的包。尝试以下操作:

Swift 5

let frameworkBundle = Bundle(for: XDWebViewController.self)
let bundleURL = frameworkBundle.resourceURL?.appendingPathComponent("XDCoreLib.bundle")
let resourceBundle = Bundle(url: bundleURL!)

let image = UIImage(named: "ic_arrow_back", in: resourceBundle, compatibleWith: nil)
print(image)

-- 原答案--

let frameworkBundle = NSBundle(forClass: XDWebViewController.self)
let bundleURL = frameworkBundle.resourceURL?.URLByAppendingPathComponent("XDCoreLib.bundle")
let resourceBundle = NSBundle(URL: bundleURL!)
let image = UIImage(named: "ic_arrow_back", inBundle: resourceBundle, compatibleWithTraitCollection: nil)
print(image)

有趣的是当你需要在cocoapod库中的源文件中做这件事的时候 我在 pod 中使用 xib 和 plist 文件时遇到了它。

下一个方法解决了。加载一个xib文件的例子:

let bundle = Bundle(for: self.classForCoder)
let viewController = CocoapodViewController(nibName: "CocoapodViewController", bundle: bundle)

我认为其他任何答案都没有描述与 Podspec 的关系。 bundle URL 使用 pod 的名称然后 .bundle 来查找资源包。此方法与资产目录一起使用,以访问 pod 内部和外部的 pod 图像。

Podspec

Pod::Spec.new do |s|
  s.name             = 'PodName'
  s.resource_bundles = {
    'ResourceBundleName' => ['path/to/resources/*/**']
  }
end

Objective-C

// grab bundle using `Class` in pod source (`self`, in this case)
NSBundle *bundle = [NSBundle bundleForClass:self.classForCoder];
NSURL *bundleURL = [[bundle resourceURL] URLByAppendingPathComponent:@"PodName.bundle"];
NSBundle *resourceBundle = [NSBundle bundleWithURL:bundleURL];
UIImage *podImage = [UIImage imageNamed:@"image_name" inBundle:resourceBundle compatibleWithTraitCollection:nil];

Swift

仅作记录:我想从存储在 CocoaPods 库中的类别中打开一个 NIB。当然[self classForCoder]还给了UIKit(因为Category),所以上面的方法都不行。

我使用一些硬编码路径解决了这个问题:

NSURL *bundleURL = [[[NSBundle mainBundle] resourceURL] URLByAppendingPathComponent:@"Frameworks/MyCocoaPodLibraryName.framework"];
NSBundle *podBundle = [NSBundle bundleWithURL:bundleURL];

CustomView *customView = [[podBundle loadNibNamed:@"CustomView" owner:self options:nil] firstObject];

这会起作用

.podspec 中添加 s.resources 除了 s.resource_bundlespod install 之后)

s.resources = 'XDCoreLib/Pod/Resources/**/*.{png,storyboard}'

那么在你的代码中,它就像:

let image = UIImage(named: "image_name.png", in: Bundle(for: type(of: self)), compatibleWith: nil)

注意:您可能需要在更新 .podspec 后 运行 pod install 才能更改您的Xcode 项目

您可以通过选择 Pods 项目、选择所需的目标并确保您位于“常规”选项卡上来检查捆绑包的 ID。

然后在代码中,您可以像这样在该 ​​Pod 中加载图片:

backgroundImageView.image = UIImage(named: "business_fellas", in: Bundle(identifier: "org.cocoapods.StandardLibrary3-0"), compatibleWith: nil)

可以创建扩展以在您的框架源代码中更轻松地访问框架包

extension Bundle {
   static func getResourcesBundle() -> Bundle? {
      let bundle = Bundle(for {your class}.self)
      guard let resourcesBundleUrl = bundle.resourceURL?.appendingPathComponent({bundle name}) else {
         return nil
      }
      return Bundle(url: resourcesBundleUrl)
   }
}

似乎出于某种原因 **/*.{extensions} 需要模式才能工作 我最终创建了这样的 podspec

s.resource_bundle = { '<BundleName>' => 'Pod/Resources/**/*.storyboard' }
s.resource = 'Pod/Resources/**/*.storyboard'

尽管我的实际路径是 Pod/Resources/.storyboard*

然后为了找到我使用的包 尽管可以通过任何方式获取捆绑包,例如通过 class 或 URL 或 bundleID 将在上述设置后工作。

您还可以查看 this answer 以获取更多参考资料。

import class Foundation.Bundle

private class BundleFinder {}

extension Foundation.Bundle {
    /// Returns the resource bundle associated with the current Swift module.
    static var module: Bundle = {
        let bundleName = "ID3TagEditor_ID3TagEditorTests"

        let candidates = [
            // Bundle should be present here when the package is linked into an App.
            Bundle.main.resourceURL,

            // Bundle should be present here when the package is linked into a framework.
            Bundle(for: BundleFinder.self).resourceURL,

            // For command-line tools.
            Bundle.main.bundleURL,
        ]

        for candidate in candidates {
            let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
            if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
                return bundle
            }
        }
        fatalError("unable to find bundle named ID3TagEditor_ID3TagEditorTests")
    }()
}

发件人:https://www.fabrizioduroni.it/2020/10/19/swift-package-manager-resources/

对我来说,以下方法有效,因为我使用的是静态 pod。


s.resource_bundle = '<BundleName>' => 'Path to resources'
s.resource = 'Path to resources'