弊社の開発環境ではサーバーサイドも人が増え、プロジェクトも複数走る事が多いので、プロジェクト毎に開発サーバーが必要になっています。
まずはアプリからサーバーが選択出来れば良いだろうとアプリを立ち上げた状態でiPhoneをシェイクすれば、ドメインを選択する為の画面が立ち上がってドメインが選択出来る機能を用意していました。
ただ、ドメインの変更を忘れてしまう事が頻発し、サーバー側で大きな変更が入るとアプリが落ちたりする事が頻発してしまいました。。
今回この問題を解決する為に1つ案を思いついたので実装してみました。
もうすぐ iOS 10
、 Swift 3
がリリース予定ですが、環境は Xcode 7.3.1
、 Swift 2.2
です。
まずはプロジェクト作成
※Gitのブランチをベースにするので必ずこのチェックは入れて下さい
新規ファイル作成
※今回は Config.swift という名前で作成します
設定のベースとなるJSONファイルを作成
※Xcodeのプロジェクトに入れるファイルではないのでXcodeの操作から離れて下さい
$(PROJECT_DIR)/scripts/API.json
というファイルを作成
{
"master": "http://fromkk.me",
"develop": "http://www.google.com/",
"feature/branch/.*": "http://yahoo.co.jp"
}
$(PROJECT_DIR)/scripts/current_domain.swift
というファイルを作成
#!/usr/bin/swift
import Foundation
/// 正規表現のマッチ機能をStringに拡張
extension String {
private func match(value: String?) -> Bool {
guard let value: String = value else {
return false
}
do {
let regexp: NSRegularExpression = try NSRegularExpression(pattern: self, options: [.CaseInsensitive])
return 0 < regexp.numberOfMatchesInString(value, options: [], range: NSRange(location: 0, length: value.characters.count))
} catch {
return false
}
}
}
struct System {
/// このファイルのフルパス
lazy var fullPath: String? = {
guard let args: [String] = NSProcessInfo.processInfo().arguments else {
return nil
}
guard let index: Int = args.indexOf("-interpret") else {
return nil
}
return args[index + 1]
}()
/// このファイルのディレクトリ
lazy var currentDir: String? = {
guard let fullPath: String = self.fullPath else {
return nil
}
var paths: [String] = fullPath.componentsSeparatedByString("/")
paths.removeLast()
return paths.joinWithSeparator("/")
}()
/// このファイルのファイル名
lazy var fileName: String? = {
guard let fullPath: String = self.fullPath else {
return nil
}
var paths: [String] = fullPath.componentsSeparatedByString("/")
return paths.popLast()
}()
/// 現在のGitのブランチ名
lazy var branch: String? = {
guard let args: [String] = NSProcessInfo.processInfo().arguments else {
return nil
}
guard let index: Int = args.indexOf("-branch") else {
return nil
}
return args[index + 1]
}()
/// JSONのファイル名
let jsonFileName: String = "API.json"
/// API.jsonの内容をパース
lazy var api: [String: String]? = {
guard let currentDir: String = self.currentDir else {
return nil
}
let path: String = "\(currentDir)/\(self.jsonFileName)"
let fileManager: NSFileManager = NSFileManager()
if !fileManager.fileExistsAtPath(path) {
return nil
}
guard let data: NSData = fileManager.contentsAtPath(path) else {
return nil
}
do {
return try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as? [String: String]
} catch {
return nil
}
}()
/// 初期ドメイン(masterだけは絶対存在する前提)
lazy var defaultDomain: String = {
guard let json: [String: String] = self.api else {
return ""
}
return json["master"] ?? ""
}()
/// ブランチ名に合ったドメイン
lazy var currentDomain: String? = {
guard let json: [String: String] = self.api, let currentBranch: String = self.branch else {
return nil
}
guard let key: String = json.keys.filter({ (key: String) -> Bool in
return ("^"+key+"$").match(currentBranch)
}).first else {
return nil
}
return json[key]
}()
}
/// 実際に実行される処理
/// ブランチ名に合ったドメイン名を出力しているだけ
var system: System = System()
print(system.currentDomain ?? system.defaultDomain)
XcodeのSchemeを編集
Provide build settings from を現在のSchemeを選択して Type a script or drag a script file from your workspace to insert its path に下記のコードをコピペ
branch=$(/usr/bin/git --git-dir=$PROJECT_DIR/.git symbolic-ref --short HEAD)
output=$(swift $PROJECT_DIR/scripts/current_domain.swift -branch $branch)
sw=$PROJECT_DIR/Config.swift
if [ ! -e $sw ]; then
touch $sw
fi
: > $sw
echo "import Foundation\n\nlet _gitBranch: String? = \"$branch\"\nlet _apiCurrentDomain: String? = \"$output\"" > $sw
※Gitでこの設定を共有するには Shared にチェックを入れておく必要があるかもです
ビルドしてみる
必要な設定は済みましたのでビルドしてみましょう。
Config.swift を選択した状態でビルドすると変化が分かりやすいと思います。
これが
こうなる!!
ブランチを変更してみる
# Terminalで下記のコマンドを実行
git checkout -b develop
再度ビルドしてみる
これが
こうなる!!!
ここまでくれば後は Config.swift に記述された定数を利用してアプリを作成していけばGitのブランチ毎に設定を変更しながら開発を進めていくことが出来ると思います。
まとめ
やっている事はSchemeのビルド時のPre-actionsで current_domain.swift を実行し、 Config.swift ファイルを書き換えているだけです。
この仕組みを応用すればブランチ毎に .plist ファイルを書き換える等色々な事が出来そうです。
READMEなど何も書いてないですがサンプルを ここ にアップしておきましたので手軽に試してみたい方はこちらからCloneしてビルドして頂ければと思います。
更に良い案があればコメントやPRを頂ければと思います。