【追記】2014.9.13 3:00
この方法はあくまで「アプリ内保存した画像のパス」の話で、Xcode上で最初から登録している画像には当てはまりません。パスに「Documents」ディレクトリが含まれないためです。
【Xcode5.1.1 + iOS 7.1 + MacOX10.9.4】
前回の解決編です。
JBOYSOFT JunjiSuzukiさんに「NSSearchPathForDirectoriesInDomains を使うのもいいかも」との助言を受けて、描いてみたコードがこれ。NSSearchPathForDirectoriesInDomainsでディレクトリのパスを取ってきて、保存しているファイル名と組み合わせて、自前でパスを作っている。
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); NSArray *ph = [select_name componentsSeparatedByString:@"/"]; NSString *fn = [ph objectAtIndex:ph.count-1]; NSLog(@"paths >> %@",paths); NSLog(@"fn >> %@",fn); path = [NSString stringWithFormat:@"%@/%@",[paths objectAtIndex:0],fn]; NSLog(@"path >> %@",path); iconImage = [[UIImage alloc] initWithContentsOfFile:path];
これだと既存のものも、起動後に保存したものも、どちらも問題なく参照出来る!NSLogによるトレースはこちら。
paths >> ( "/var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/Documents" ) fn >> icon20140913003532.png path >> /var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/Documents/icon20140913003532.png
気になったので、前回描いたコードで取得されるパスを確認してみる。前回のコードはコレ。
NSArray *phrases = [imageName componentsSeparatedByString:@".png"]; NSString *filename = [phrases objectAtIndex:0]; NSString *path= [[NSBundle mainBundle] pathForResource:filename ofType:@"png"]; //アプリ内保存した直後の画像は、path が nullになる NSLog(@"path >> %@",path); //保存直後の画像はNSBundleでパスが取れないための対処(アプリが再起動しないとダメみたい) UIImage *iconImage; if (path == NULL) { iconImage = [UIImage imageNamed:imageName]; } else { iconImage = [[UIImage alloc] initWithContentsOfFile:path]; }
※ imageNameには、”../Documents/icon20140912171442.png”のようなパスが入っている。
アプリ起動前に保存されている画像について、NSLogで表示されるパスを見ると・・・
path >> /var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/xxxxxx.app/../Documents/icon20140913003017.png
と、アプリ名(xxxxxx.app/../)がはさまってる。この違いは何?NSBundleだとこうなるの?
更に、冒頭の修正コードをアプリ名(xxxxxx.app/../)がはさまってるパスに変更して参照してみる。
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); NSArray *ph = [select_name componentsSeparatedByString:@"/"]; NSString *fn = [ph objectAtIndex:ph.count-1]; NSLog(@"paths >> %@",paths); NSLog(@"fn >> %@",fn); NSArray *paths2 = [[paths objectAtIndex:0] componentsSeparatedByString:@"Documents"]; path = [NSString stringWithFormat:@"%@iconFaceCam.app/%@",[paths2 objectAtIndex:0],select_name]; NSLog(@"path >> %@",path); iconImage = [[UIImage alloc] initWithContentsOfFile:path];
NSLogの出力結果がこれ。
paths >> ( "/var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/Documents" ) fn >> icon20140913012801.png path >> /var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/xxxxxx.app/../Documents/icon20140913012801.png
動作としては、こちらでも問題なく動きました。
で、結論としては、アプリ内保存のファイル参照では・・・
・NSSearchPathForDirectoriesInDomainsでドキュメントディレクトリを取得する。
・ドキュメントディレクトリ+ファイル名でパスを生成する。
・生成したパスを使って、initWithContentsOfFileで参照する。
ということになるんだけれど、そもそも何で・・・
[[NSBundle mainBundle] pathForResource:filename ofType:@”png”]
でパスが取得できないのか、がわからずモヤモヤします…。
とりあえずは余計なifとか要らなくなったので、よしとして先に進みます。
JBOYSOFT JunjiSuzukiさんに感謝。