【Swift】R.swiftが優秀すぎるので紹介してみる

80件のシェア(ちょっぴり話題の記事)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんぬづは、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を追加します。
スクリーンショット_2016-08-09_11_39_31

追加されたRun ScriptをCheck Pods Manifest.lockCompile Sourcesの間にドラッグして移動します。
スクリーンショット_2016-08-09_11_41_25

Run Scriptに"$PODS_ROOT/R.swift/rswift" "$SRCROOT"と記述します。
スクリーンショット 2016-08-09 11.41.58

R.generated.swiftの追加

Run Scriptを設定したら一度ビルドします。
するとR.generated.swiftファイルがプロジェクトのルートディレクトリに追加されるので、これをプロジェクトの中に追加します。

スクリーンショット 2016-08-09 11.34.16

スクリーンショット 2016-08-09 11.35.00

スクリーンショット 2016-08-09 11.35.11

プロジェクトがビルドされるたびに、この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が必要でした。

スクリーンショット 2016-08-09 11.24.49

スクリーンショット 2016-08-09 11.24.58

画像リソースを取得する

画像リソースは以下のようになります。

// 直接プロジェクトに画像を追加している場合
let tanakaFromFile = R.image.tanakaJpg()
// xcassets内に画像を追加している場合
let tanakaFromXCAssets = R.image.tanaka()

直接プロジェクトに画像を追加している場合は以下のようにファイルの階層の中に含ませている場合を指します。

スクリーンショット 2016-08-09 11.29.19

その他

その他、フォントや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を使うとその手間が一気になくなりそうです。 積極的に導入していこうと思います。?