4
1

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 1 year has passed since last update.

Bundle.moduleを自前で取得する方法 (SwiftPM)

Last updated at Posted at 2023-01-21

はじめに

SwiftPM (Swift Package Manager)を使ったライブラリを開発するとき、
Bundle.module、使いたくないですよね?

swift package init --type library

↑を実行してパッケージ基盤の生成直後にBundle.moduleを使おうとすると、

Bundle.moduleとか知らねぇよ」と怒られてしまいます。
黙ってnilを返してくれればいいのに、プロパティの存在が無くなってビルドエラーになるのは使いにくいと思います。

代替方法2選

1. allBundles

static var alt1Bundle: Bundle? {
    for bundle in Bundle.allBundles {
        if let subBundleURL = bundle.url(forResource: "", withExtension: "bundle"),
           let subBundle    = Bundle(url: subBundleURL) {
            return subBundle
        }
    }
    return nil
}

Bundle.allBundlesの中から探す方法です。
ループを回すのでちょっと非効率かもしれませんが、広い範囲を調べるのでBundle.module相当が見つかる可能性は高そうです。

2. BundleFinder

static var alt2Bundle: Bundle? {
    class BundleFinder {}
    let bundle = Bundle(for: BundleFinder.self)
    if let subBundleURL = bundle.url(forResource: "", withExtension: "bundle") {
       return Bundle(url: subBundleURL)
    }
    return nil
}

Bundle(for:)の引数にはクラスしか渡せないので、BundleFinderと呼ばれる1テクニックを使います。これによってstructenumでも使えます。
知らない人が見ると「このクラスは何?」となる可能性は考えられます。

解説

処理の流れは以下の通り。

  1. UnitTestがあるBundle「(ライブラリ名)Tests.xctest」を取得する。
  2. その下にある「(ライブラリ名)_(ライブラリ名)Tests.bundle」を探す。
  3. そのBundleがBundle.module相当です。(独自研究)
.
├── xxxxxxxTests.xctest
│   ├── xxxxxxxTests
│   ├── xxxxxxx_xxxxxxxTests.bundle  ← Bundle.module
│   │   ├── Test.txt

Bundle.module生成方法

Bundle.moduleを使う方法も書いておきます。

1. Package.swift内のtestTargetresourcesの記述を追加する。(targetでも可)

.testTarget(
    name: "xxxxxxxTests",
    dependencies: ["xxxxxxx"],
    resources: [
        .process("./Test.txt")
    ]
),

2. Sources配下にファイル(本例ではTest.txt)を追加する。

├── Package.swift
├── Sources
│   └── xxxxxxx
│       ├── ・・・
└── Tests
    └── xxxxxxxTests
        ├── Test.txt

3. ビルドする。
4. Bundle.moduleが使えるようになる。

おわりに

ライブラリの開発中は問題がなかったけど、ライブラリをアプリに組み込んだ状態でビルドでしたら「Type 'Bundle' has no member 'module'」が出た!という問題を筆者は経験したことがあります。
ライブラリのテスト時には使うけど、ライブラリの配布時にはパッケージに含めないファイルがあると発生しがちだ思われます。
テスト時は本物のファイルで、配布時は空ファイルにすればいいのか?などと思案していますが、簡単で効果的な方法に辿り着いていません。
良い方法があったら教えてください。

  1. 呼ばれてないかもしれない:stuck_out_tongue:

4
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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?