LoginSignup
8
1

More than 5 years have passed since last update.

CocoaTouchFramework上でImageLiteralを使用する方法

Last updated at Posted at 2018-12-01

SwiftでCocoaTouchFrameworkを開発していて、特に不便だなと思うのは、 ImageLiteralが使用出来ないということです。

これは、ImageLiteralが、mainのBudleからリソース取得しようとするため、使用すると、mainのBundleで画像が無いとクラッシュしてしまうためです。

しかし、Xcodeの機能上、Frameworkのプロジェクト上でもImageLiteralは使えますし、コンパイルも通るので、使えないのはなんとももどかしいところです。

なので、今回は、そこをなんとかハックして、CocoaTouchFramework上でImageLiteralを使用する方法を見つけたので、紹介します。

_ExpressibleByImageLiteral

_ExpressibleByImageLiteralというProtocolを利用すれば、Framework上でImageLiteralを使用することができます。

ただし、このProtocolはXcodeの予測変換で出てこないので、実際に打ち込む必要があるので気をつけましょう。

とりあえず簡単に実装してみると以下のようになります。

// _ExpressibleByImageLiteralは予測変換で出てこないImageLiteralのProtocol
struct FrameworkImageLiteral: _ExpressibleByImageLiteral {

    let image: UIImage

    // pathにはImageLiteralで指定したImageの名前が入ってくる
    init(imageLiteralResourceName path: String) {
        // 通常のImageLiteralの動作と同じように初期化できなかったらアプリを落とすために!にする
        self.image = UIImage(named: path, in: Bundle.current, compatibleWith: nil)!
    }
}

Bundle.currentに関しては、以前に以下の記事を書いたので、それを参考にしてください。

SwiftのフレームワークでBundleを取得する方法

実際に使ってみるとこんな感じ

let image = (#imageLiteral(resourceName: "image_name") as FrameworkImageLiteral).image

これでFramework上のBundleからImageLiteralを使用して画像を取得できます。

なんかイケてなくね?

(#imageLiteral(resourceName: "image_name") as FrameworkImageLiteral) 

しかし、キャストするのが少し鬱陶しいので、もう少しいい感じにする方法を考えてみました。

いい感じにしてみた。

まずは最初の_ExpressibleByImageLiteralを実装した構造体でUIImageを生成せずに、Pathだけ保持するように変更します。

struct FrameworkImageLiteral: _ExpressibleByImageLiteral {

    let path: String

    init(imageLiteralResourceName path: String) {
        // ここでImageを生成せずにpathだけ保持しておく
        self.path = path
    }
}

次にUIImageのextensionで、Frameworkimageliteralを引数にして、先ほどFrameworkImageLiteralで行なっていたUIImageの初期化をこちらで行います。

extension UIImage {

    convenience init!(literal: FrameworkImageLiteral) {
        self.init(named: literal.path, in: Bundle.current, compatibleWith: nil)!
    }
}

それで実際に使用するとこんな感じになります。

let image = UIImage(literal: #imageLiteral(resourceName: "image_name"))

変にキャストが挟まらないので、いい感じになりました。

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1