CocoaPods を使って、自社用の共通ライブラリを整備中。
リソースファイルの扱いをどうすると一番やりやすいかを今日は悩んでいたのでメモ。
podsspecに下記のように書くと、そのリソースが MainBundleに含まれる。
spec.resources = "My/Resources/*"
この場合は、名前の重複に気をつける必要がアリ。
出来る限り、本体のアプリには影響を与えないようにライブラリを作成したいので、Bundleを試してみた。
Bundleの指定
spec.ios.resource_bundle = {'My-Resources' => ["My/Resources/*"]}
のようにかけば別のBundleになる。
上記の例だと、My/Resources/ 以下を全て含んだ My-Resources という名前のBundleができる。
ローカライズのファイル
ja.lproj/Localized.strings en.lproj/Localized.strings
などは、
ja.lproj, en.lproj のディレクトリも含めてバンドルにする必要があるので、
Resources/*
のようなディレクトリ指定にする。
Resouces/**/Localized.strings
のようなファイル指定だとディレクトリが出来ないのでダメ。
Bundleからリソース読み込み
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"My-Resources" ofType:@"bundle"]; NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
のBundleを使用する。
ローカライズの文字列を取得するには
NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment)で取得が可能。
Bundleにすると、Key名の重複を気にしなくてもいいのがマル。
Storyboardの扱い
Bundleの中にStoryboardファイルを入れた場合、
UIStoryboard#storyboardWithName:(NSString *)name bundle:(NSBundle *)storyboardBundleOrNil;
にて、bundleを適切なものを設定すれば読み込める。
ただし、Storyboardに画像を設定していて、その画像をAssetCatalog(xcassets)で管理している場合は、以下のメッセージとともに、画像読み込みが出来なかった。
Could not load the "imageName" image referenced from a nib in the bundle with identifier "(null)"
bundle identifierが(null)となっているのが気になるが、そういうものなのだろうか...
AssetCatalogで管理しているUIImageの扱い
StoryboardをBundleにした場合、上述のように画像読み込みが出来なかった訳だが、
StoryboardとAssetCatalog (Images.xcassets)を同じBundleにしても同様に読み込みは出来なかった。
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"My-Resources" ofType:@"bundle"]; NSBundle *bundle = [NSBundle bundleWithPath:bundlePath]; UIImage *image = [UIImage imageNamed:@"btnName" inBundle:bundle compatibleWithTraitCollection:nil];
としても UIImageは取得出来ない。
[UIImage imageNamed:@"btnName"]
でなぜか画像が取得できる。
ということで、
AssetCatalog (Images.xcassets) をBundleに入れたとしても、
コンパイルしてAssets.carにまとめられるときに、MainBundleのものとして生成されているのと想像。
試してはないが、AssetCatalogを使わず、画像ファイルを直接扱えば、別Bundleとして扱える気がする。
AssetCatalogを使う場合には、画像名が重複しないようにプレフィックスなどをつける運用が必要。
現状まとめ
私の場合、StoryboardやAssetCatalogはデザイナーさんに通常のプロジェクトと同じように触って欲しいので、あれこれせずにMainBundleとして取り込む方針に。