soranoba
soranoba Author of soranoba.net
programming

CocoaPodsで依存に追加したFramework内の画像が正常に読み込めない場合の対処法

画像リソースの使い方

CocoaPodsに対応したライブラリに画像リソースを含める場合、podspecにresource_bundlesの記載を追加し、その画像をコードから利用する場合はBundleを明示的に指定する必要があります。

Pod::Spec.new do |s|
  s.resource_bundles    = { 'Resources' => ["package1/*.xcassets"] }
end
public extension Bundle {
    static var pkg1ResourceBundle: Bundle {
        let frameworkBundle = Bundle(for: DummyClass.self)
        guard let resourceURL = frameworkBundle.resourceURL?.appendingPathComponent("Resources.bundle"),
              let bundle = Bundle(url: resourceURL) else {
            // Using Carthage
            return frameworkBundle
        }
        // Using CocoaPods
        return bundle
    }
}

public extension UIImage {
    static func pkg1Image(named: String) -> UIImage? {
        return UIImage(named: named, in: Bundle.pkg1ResourceBundle, with: nil)
    }
}

private class DummyClass {}

他のリソースは読み込めるのに、画像が正しく読み込めない場合

ここからが本題です。上記の実装をして正しくBundleを指定しても画像だけ正常に読み込めない場合があります。
これは、UIImage(named:in:with:)がBundle identifierのみを参照する為、Bundle identifierが重複していた場合、指定したBundleと異なるBundleが読み込まれるのが原因です。

例えば、2つのライブラリで以下のように指定していた場合、2つのResource bundleのBundle identifierがともにorg.cocoapods.Resourcesとなってしまい、UIImage(named:in:with:)では正しく読み込めなくなってしまいます。

Pod::Spec.new do |s|
  s.resource_bundles    = { 'Resources' => ["**/*.xcassets"] }
end

Bundle identifierが競合しているのが原因なので、これを解消することでこの問題を解決できます。
なお、xibから画像を参照する場合は同一ターゲットの画像が読み込まれるので、問題は発生しません。

方法1

1つ目の方法は、シンプルにResource bundleのBundle identifierのみを変更する方法です。

Pod::Spec.new do |s|
  s.resource_bundles    = { 'SKPResources' => ["**/*.xcassets"] }
end

このようにObjective-C時代にあった、アプリケーションプレフィックスなどを用いてユニークになるようにすれば競合は解消されます。

方法2

2つ目の方法は、Bundle identifierを明示的に指定する方法です。

Pod::Spec.new do |s|
  s.pod_target_xcconfig = { 'PRODUCT_BUNDLE_IDENTIFIER' => 'net.soranoba.package' }
end

このように指定することで、ライブラリのBundle identifierと同じものがResource bundleで使用されるようになります。
しかし、複数のResource bundleを使い分けようとした場合に競合するので、同様の不具合が発生する可能性があります。


この記事の挙動は以下のレポジトリから確認することができます.

  • https://github.com/soranoba/iOS-SandBox/tree/CocoaPods-FrameworkResourceImageCannotRead

(Updated: )

comments powered by Disqus