はじめに
ビルド環境の切り替えにSchemeを利用しているプロジェクトは結構あると思います。
接続先の変更やMockへの差し替えなど行うのに便利です。
私のプロジェクトでは環境ごとにSchemeを分けており、SwiftPackageを用いたマルチモジュール化を行っていました。
その中でSwiftPackageからSchemeを取得することができずに困ったので、対応法を共有しておきます。
概要
マルチモジュール化の中でInfra層をSwift Packageに切り分けていました。
Infra層でAPIの接続先を切り替えたかったのですが、Active Compilation Conditionsで指定している値(DEBUG/STG/RELEASE)などをSwift Packageから取得することができませんでした。
スキームを取得するためのSwiftPackageの作成
結論から言うと、スキームの情報を取得するために新規でSwiftPackageを作成しました。
SwiftPackage側からアプリモジュールの情報を直接参照することはできないので、起動時などに参照したいSwiftPackage側に渡してあげる必要があります。
例で言うとInfra層に直接情報を渡してあげても良いのですが、マルチモジュール化を進めていく中で他のモジュールでも必要になる可能性が高いため、今回は独立したSwiftPackageを作成して他モジュールから参照する形にしました。
Configurationの定義
作成したSwiftPackageに以下を記述します。
まずスキームごとにenumのcaseで下記のように定義しておきます。
public enum SchemeConfiguration {
case debug
case staging
case release
}
Schemeを渡す
利用する側で下記のProviderを用いてスキームにアクセスできるように定義します。
public struct SchemeConfigurationProvider {
// 内部で保持する変数
private static var _config: SchemeConfiguration?
/// 初期化用
public static func initialize(config: SchemeConfiguration) {
self._config = config
}
/// スキーム情報を取得するプロパティ
public static var config: SchemeConfiguration {
guard let config = _config else {
fatalError("SchemeConfigurationProvider not initialized.")
}
return config
}
}
AppDelegateでの初期化処理
上記でSwiftPackage側の定義は完了ですが、そのままでは使えません。
SchemeConfigurationProviderの初期化処理でアプリ側からActive Compilation Conditionsなどで定義している値を利用してスキームを渡してあげる必要があります。
/// Schemeに応じたConfiguraionを渡す
func setupSchemeConfiguration() {
var config: SchemeConfiguration {
#if DEBUG
return .debug
#elseif STG
return .staging
#elseif RELEASE
return .release
#else
fatalError("Unknown configuration")
#endif
}
SchemeConfigurationProvider.initialize(config: config)
}
起動時に渡したいので、AppDelegateのdidFinishLaunchingWithOptions
で呼んであげればOKです。あとは利用箇所でSwiftPackageをimportして下記のようにアクセスすれば問題なくスキームごとの値を取得することができるようになりました。
import SchemeConfig
enum APIConfig {
static let hostURL: String = {
switch SchemeConfigurationProvider.environment {
case .debug:
return "https://hogehoge-debug.com/"
case .staging:
return "https://hogehoge-stg.com/"
case .release:
return "https://hogehoge.com/"
}
}()
}
最後に
SwiftPackage側から取得する方法が何かしらあるはずと思って探していて詰まったのですが、シンプルにApp側から渡してあげればいいだけでした。
SwiftPackageとSchemeを利用しているプロジェクトがあれば参考にしてみてください!