32
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

もちろん俺らは抵抗するで?技術で🤜🤛Advent Calendar 2017

Day 2

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

Last updated at Posted at 2017-12-06

#とりあえずおさらい

Cocoa Touch Frameworkで初めて開発した時にハマるあるあるなのですが、UIImageを取得する際には、

public init?(named name: String)

ではなく、

@available(iOS 8.0, *)
public init?(named name: String, in bundle: Bundle?, compatibleWith traitCollection: UITraitCollection?)

を使用しなければなりません。

前者の方はメインのBundleからUIImageを取得するメソッドなので、メインであるアプリ側のBundleからUIImageを取得しようとしてしまいます。
メインのBundleがフレームワークのBundleではないので、フレームワーク側で前者を使用した場合、正しい画像取得ができなくなってしまうためです。

画像だけでなく、xibなどのリソースファイルをフレームワークのプロジェクト上で取得する際には、後者のような通常のアプリのプロジェクトで使用しているメソッドにさらにBundleを引数で指定するメソッドで取得しなければいけなかったりするので注意が必要です。

#classでバンドルを取得する場合

フレームワーク上では、フレームワークのBundleを取得しなければならないことがわかったので、その取得方法について見ていきましょう。
classで取得する場合は以下のメソッドを利用します。

Bundle
public init(for aClass: Swift.AnyClass)

このメソッドを使用して以下の処理を実行すれば、classが所属するBundleを取得することが可能です。

FrameworkClassSample.swift
let bundle = Bundle(for: type(of: self))

#enum・structの場合

Swiftでenumやstructの機能がかなり強化されたので、フレームワークでも使いたいパターンもあります。
その際もenumの値によって画像なんかをBundleから取得したいとかってよくあると思います。

そんな時、先ほどのclassで使用した方法は、あくまで、classが所属するBundleを取得するのでコンパイルエラーを起こしてしまいます。

そういう場合は、下記のように仮のクラスを作成して、そこからBundleを取得するのがいいのではないかと思います。

enum
enum hoge {
    
    case fuga
    case piyo
    
    var image: UIImage? {
    	//仮のクラスを作ってそこからBundle取得する
        class DummyClass {}
        let bundle = Bundle(for: type(of: DummyClass()))
        
        switch self {
        case .fuga:
            return UIImage(named: "fugaImage", in: bundle, compatibleWith: nil)
        case .piyo:
            return UIImage(named: "piyoImage", in: bundle, compatibleWith: nil)
        }
    }
}
struct
public struct SampleStruct {
    var image: UIImage? {
    	//仮のクラスを作ってそこからBundle取得する
        class DummyClass {}
        let bundle = Bundle(for: type(of: DummyClass()))
        return UIImage(named: "structImage", in: bundle, compatibleWith: nil)
    }
}

#extension作ったよ
さすがに毎回仮のクラスを作るのは面倒なのでextension作ったよ。

Bundle+current.swift
extension Bundle {
    static var current: Bundle {
        class DummyClass{}
        return Bundle(for: type(of: DummyClass()))
    }
}
呼び出す時
let bundle = Bundle.current
32
18
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
32
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?