【Swift】R.swiftが優秀すぎるので紹介してみる
こんぬづは、Steamのセールでゲームを買ったはいいが、家にネット回線がまだひかれておらずゲーム本体のダウンロードすらできていない田中です。
今回は先日発見したR.swiftというライブラリが、導入コストに対する効果が高そうなので紹介します。 このライブラリ、Fabric.appにも導入されている模様です。 Building Fabric.app in Swift
概要
なにができるライブラリ?
R.swiftの利点は以下になります。
- コード補完でリソースファイルにアクセスすることができる
- リソースファイル取得時に型も補完してくれる
- 文字列指定による動的な指定をしなくてよいので静的に解析することができる(コンパイル時にエラーを出してくれる)
なにがいいの?
リソースファイルにアクセスする際によく取り上げられる問題として、文字列指定によって取得しなければいけない点が挙げられます。 これはTypoや該当ファイルがそもそもなかったりが原因で実行時に急にアプリが落ちるバグの温床になりがちです。 そのためリソースファイルをコード補完によって型も含めてチェックすることができるのは大きな利点になります。
導入方法
podからのインストール
pod 'R.swift'
とPodfileにpodを追加して、pod install
Run Scriptの設定
Project > TARGETS > Build PhasesでRun Scriptを追加します。
追加されたRun ScriptをCheck Pods Manifest.lock
とCompile Sources
の間にドラッグして移動します。
Run Scriptに"$PODS_ROOT/R.swift/rswift" "$SRCROOT"と記述します。
R.generated.swiftの追加
Run Scriptを設定したら一度ビルドします。
するとR.generated.swift
ファイルがプロジェクトのルートディレクトリに追加されるので、これをプロジェクトの中に追加します。
プロジェクトがビルドされるたびに、このR.generated.swiftファイルの中にリソースファイルへのアクセスが構造体として定義されて、それによって型指定によるリソースへのアクセスが可能になるという仕組みのようです。
使い方
StoryboardからViewControllerを取得する
例えばソースコードでStoryboardの特定のViewControllerを取得する際は以下のように書くと思われます。 (先述した「なにがいいの?」で指しているのは箇所は"Main"や"FirstViewController"と記述している箇所です。)
// Standard Use let initialViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? ViewController let firstViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("FirstViewController") as? ViewController
これをR.swiftで書くと、
// R.swift let initialViewController = R.storyboard.main.initialViewController() let firstViewController = R.storyboard.main.firstViewController()
となります。
ここでさらに着目すべきは適当な型がすでに確定している点です。
元の書き方だとas? ViewController
が必要でした。
画像リソースを取得する
画像リソースは以下のようになります。
// 直接プロジェクトに画像を追加している場合 let tanakaFromFile = R.image.tanakaJpg() // xcassets内に画像を追加している場合 let tanakaFromXCAssets = R.image.tanaka()
直接プロジェクトに画像を追加している場合は以下のようにファイルの階層の中に含ませている場合を指します。
その他
その他、フォントやLocalizable Stringにも対応しているようです。
// フォント let defaultUseFont = UIFont(name: "San Francisco", size: 42) let rUsedFont = R.font.sanFrancisco(size: 42) // Localizable String let defaultUseLocalize = String(format: NSLocalizedString("welcome.withName", comment: ""), locale: NSLocale.currentLocale(), "Arthur Dent") let rUsedLocalize = R.string.localizable.welcomeWithName("Arthur Dent")
注意点
リソースを追加したら都度ビルドしよう
R.generated.swiftの追加の項でも書きましたが、新たにリソースファイルを追加したり修正した場合は都度プロジェクトをビルドする必要があります。 それによってR.swiftによって参照できるリソースファイルを最新に保つことができます。
R.generated.swiftのコンフリクト
R.generated.swiftによる余計なgitのコンフリクトを防ぐために、.gitignoreに登録しておいたほうがよいです。
.gitignoreファイルに*.generated.swift
を追記しましょう。
まとめ
ここはなかなか個人的にも悩んでいた問題でした。 例えば自分の場合、enumでイメージを指定するStringを自前で定義していたり、それはStoryboardからのViewControllerの取得でも、Localizable Stringにも言えたことでしたが、このR.swiftを使うとその手間が一気になくなりそうです。 積極的に導入していこうと思います。?