はじめに
多くのアプリ開発者はプロジェクトにファイルの追加、ファイルのリネーム、ファイルの移動などをよくすると思います。さらにそのプロジェクトをチームでGitを用いて開発すると思います。ただしXcodeの仕組み上、ファイルのリネームや移動等で*.xcodeproj
の内容が変更されるのでGit管理でコンフリクトが頻繁に起きてしまう問題を抱えています。
コンフリクト解決に時間を取られてしまうので、チーム全体の開発スピードを鈍足にしてしまいます。
本記事では、上記の問題を解決するXcodeGenの導入方法とCarthage・CocoaPodsとの連携について説明します。
ファイル構造
説明にあたり以下のようなファイル構造となっています。
.
├── .git
├── .gitignore
├── .swiftformat
├── .swiftlint.yml
├── Cartfile
├── Cartfile.resolved
├── Carthage
├── Extensions.framework
├── Modules
├── Podfile
├── Podfile.lock
├── Pods
├── SampleApp
├── SampleAppUITests
├── SampleProject.xcodeproj
├── SampleProject.xcworkspace
└── project.yml
XcodeGenとは
https://github.com/yonaskolb/XcodeGen
XcodeGenはXcodeのプロジェクトの設定を*.yaml
で定義して*.xcodeproj
を生成するツールです。
なのでGitで*.xcodeprojを管理せずに*.yaml
を使うことでXcode原因のコンフリクトを回避することができます。
YAMLの定義例
name: SampleProject
options:
bundleIdPrefix: com.messyu.sampleproject
targets:
SampleApp:
type: application
platform: iOS
deploymentTarget: "12.0"
sources:
- path: SampleApp
settings:
configs:
debug:
CUSTOM_BUILD_SETTING: my_debug_value
release:
CUSTOM_BUILD_SETTING: my_release_value
SWIFT_VERSION: 5.0
dependencies:
- target: TodoList
- target: TodoDetail
- carthage: RxSwift # carthageで生成したフレームワークを利用
- framework: Extensions.framework # 自作したフレームワーク
TodoList:
type: framework
platform: iOS
deploymentTarget: 12.0
sources:
- path: Modules/TodoList
buildPhase: none
settings:
PRODUCT_BUNDLE_IDENTIFIER: com.messyu.todolist
INFOPLIST_FILE: Modules/TodoList/Info.plist
SWIFT_VERSION: 5.0
dependencies:
- carthage: RxSwift
TodoDetail:
type: framework
platform: iOS
deploymentTarget: 12.0
sources:
- path: Modules/TodoDetail
buildPhase: none
settings:
PRODUCT_BUNDLE_IDENTIFIER: com.messyu.tododetail
INFOPLIST_FILE: Modules/TodoDetail/Info.plist
SWIFT_VERSION: 5.0
dependencies:
- carthage: RxSwift
Carthageとの連携
XcodeGenはCarthageで生成したフレームワークを利用できるように設定することができます。
Carthageで生成したいフレームワークを記述します。
github "ReactiveX/RxSwift" ~> 5.0
Cartfileをもとにcarthageコマンドでフレームワークを生成します。
フレームワークはCarthage -> Build -> iOS
ディレクトリに生成されるので、確認することができます。
$ carthage update --platform iOS --no-use-binaries
では実際にXcodeGenコマンドで*.xcodeproj
を生成しましょう。
$ xcodegen
CocoaPodsとの連携
XcodeGenで*.xcodeproj
生成できたら、CocoaPodsと連携させましょう。
Podfileの定義例
# Uncomment the next line to define a global platform for your project
platform :ios, '12.0'
def install_swiftformat
pod 'SwiftFormat/CLI'
# ビルドするたびにSwiftFormatを実行させる
script_phase :name => 'Run SwiftFormat',
:script => 'if which "${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat" >/dev/null; then
"${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat" . --self insert
else
echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat"
fi'
end
def install_swiftlint
pod 'SwiftLint'
# ビルドするたびにSwiftLintを実行させる
script_phase :name => 'Run SwiftLint',
:script => 'if which "${PODS_ROOT}/SwiftLint/swiftlint" >/dev/null; then
"${PODS_ROOT}/SwiftLint/swiftlint" autocorrect
"${PODS_ROOT}/SwiftLint/swiftlint"
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi'
end
target 'SampleApp' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for SampleApp
install_swiftformat
install_swiftlint
end
target 'TodoList' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for SampleApp
install_swiftformat
install_swiftlint
end
target 'TodoDetail' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for SampleApp
install_swiftformat
install_swiftlint
end
#gitignoreの設定
*.xcodeproj
が管理されないように.gitignore
に設定を記述します。
また、Carthageで作成したフレームワークとCocoaPodsのPodfile.lock
は不必要なので管理対象から除外します。
### Carthage ###
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
Carthage/
Cartfile.resolved
# CocoaPods - Only use to conserve bandwidth / Save time on Pushing
# - Also handy if you have a large number of dependant pods
# - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE
Pods/
Podfile.lock
### Xcode ###
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Xcode Patch
*.xcodeproj/*
!*.xcodeproj/project.pbxproj
!*.xcodeproj/xcshareddata/
!*.xcworkspace/contents.xcworkspacedata
/*.gcno
### Xcode Patch ###
**/xcshareddata/WorkspaceSettings.xcsettings
### macOS ###
# General
.DS_Store