Swiftでプロジェクト内のファイルを取得する際の注意点2つ
こんにちは、プログラマーの@Yuuです。
以前に「Swiftでプロジェクト内のファイルを取得する」という記事を書きました。
プロジェクト内のファイルを取得する際にはBundle.main.path(forResource:ofType:)
というメソッドを使用して、ファイルまでのパスを取得します。
しかし、このメソッドを用いた際にnil
を返す事がよくあるので、nil
が返ってしまう現象が起きる原因と対応策をご紹介します。
解説を行う環境
- OS:macOS Sierra 10.12.2
- Xcode:8.2.1
- Swift:3.0.2
スポンサーリンク
そもそもBundle.main.pathが何をやっているか
そもそもBundle.main.path(forResource:ofType:)
が何をやっているのかを理解すると、何が原因でnil
が返ってしまうかが分かりやすいので、まずそちらの説明から書きます。
「そんなの興味ないぜ!解決策早く教えてくれ!」という方は読み飛ばしちゃって下さい。
Bundle.main.path(forResource:ofType:)
はそのプロジェクトをビルドした後も、パッケージ化されたリソースの保存領域を見にいく事が出来ます。
「つまりそれってどういう事なのさ?」となるかと思いますが、
これはシミュレータを使いBundle.main.path(forResource:ofType:)
をprint
するとわかりやすく
「text.txt」「pic.png」といった、いくつかのリソースファイルが入っているのが分かります。
このフォルダがつまり「パッケージ化されたリソースの保存領域」なわけです。
そしてこれらのリソースファイルというのは
プロジェクト -> Build Phases -> TARGETS[ビルドするプロジェクト] -> Copy Bundle Resources
で表示されているリソースファイルと同じものになります。
つまり端的に書いてしまうとBundle.main.path(forResource:ofType:)
は、Copy Bundle Resourcesに登録されているファイルを取得する事が出来る!という事になります。
Bundle.main.pathがnilを返す際の2つの原因と対応策
お待たせしました。
Bundle.main.path(forResource:ofType:)
を使った際にnil
が返ってくる原因になりそうな2つの対応策です。
特に1の「Copy Bundle Resourcesに登録されていない」はnil
が返る原因になりやすく、最初のうちは分かりづらい部分かと思うので、nil
が返ってきてしまった場合はチェックしてみて下さい。
1. Copy Bundle Resourcesに登録されていない
上でご紹介した
プロジェクト -> Build Phases -> TARGETS[ビルドするプロジェクト] -> Copy Bundle Resources
この一覧に取得したいファイルがない場合、ファイルを取得した際にnil
が返ります。
詳しい解説は上で書きましたが、Copy Bundle Resourcesで表示されているファイルというのは、このプロジェクトで使用するファイルの一覧なので、ここにファイルが登録されていなければ当然プロジェクト内のファイルのpathを取得するという事が出来ません。
このCopy Bundle Resourcesにファイルが登録されていない場合の1番の原因は、ファイルを追加しようとした際に
このようにAdd to targetsで目的のプロジェクトのチェックマークを付け忘れた場合が1番多いんじゃないかと思います。
このチェックマークを外すという事は「追加しようとしているファイルは目的のプロジェクトに追加しません」と言っているようなものなので、当然ファイルを取得しようとしてもnil
が返ってしまいます。
もし後からCopy Bundle Resourcesにファイルを追加したい場合は
Copy Bundle Resourcesの+ボタンから追加する方法と
このようにTarget Membershipから追加したいプロジェクトのチェックマークを付ける事で、Copy Bundle Resourcesの一覧に表示されるようになります。
2. ファイル名・拡張子の指定方法を間違えている
例えば「text.txt」というファイルを追加した場合は
1 2 3 4 |
Bundle.main.path(forResource: "text", ofType: "txt") //正しい Bundle.main.path(forResource: "text", ofType: "json") //間違い(拡張子が間違っている) Bundle.main.path(forResource: "text.txt", ofType: "txt") //間違い(forResourceはファイル名のみ) |
上の例のように拡張子を間違える事は少ないと思いますが、慣れないと下のミスは起こりえそうですね。 forResource
には拡張子は含めず書くのでご注意を。
あとがき
Bundle.main.path(forResource:ofType:)
は使えると便利なのですが、最初何やっているのか良く分からずエラーが起きる事も多いので書いてみました。
ではでは
今回はこの辺で!ヽ(•̀ω•́ )ゝ✧