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
記事が気に入ったらチップを送ることができます!
You can give me a cup of coffee :)
Kyash ID: soranoba
Amazon: Wish List
GitHub Sponsor: github.com/sponsors/soranoba
PayPal.Me: paypal.me/soranoba
(Updated: )