I Finally Adopted XcodeGen Across my Projects
After a long while, I have finally adopted XcodeGen across my projects.
I have been meaning to do this for a long time, having used RubyMotion and loved how it manages macOS/iOS projects with a Rakefile. e.g.:
Motion::Project::App.setup do |app|
app.name = 'My app name'
app.identifier = 'my.bundle.id'
app.short_version = '1.19.0'
app.version = '130'
app.deployment_target = '8.0'
app.archs['iPhoneOS'] << 'arm64'
app.archs['iPhoneSimulator'] << 'x86_64'
app.interface_orientations = [:portrait]
app.info_plist['UIRequiresPersistentWiFi'] = true
app.info_plist['UILaunchStoryboardName'] = 'Launch Screen'
app.info_plist['CFBundleIcons'] = { 'CFBundlePrimaryIcon' => { 'UIPrerenderedIcon' => true }}
app.info_plist['CFBundleIcons'] = {
'CFBundlePrimaryIcon' => {
'CFBundleIconName' => 'AppIcon',
'CFBundleIconFiles' => ['AppIcon20x20', 'AppIcon29x29', 'AppIcon40x40', 'AppIcon60x60']
}
}
…and to a certain extent, the usage of package.json
in the JavaScript world.
XcodeGen is a tool that lets you define your project in a project.yml
file and then generate the Xcode project for you. So you would check in project.yml
and not your .xcodeproj
and .xcworkspace
files (directories). You run xcodegen
, and it re-generates an update-to-date .xcodeproj
. If you use CocoaPods, run pod install
again each time you run xcodegen
.
The benefits of using XcodeGen’s project.yml
over manually editing Xcode project and workspace files are:
- No more pesky merge conflicts in your project files
- Much easier to copy and paste and edit an
.yml
file - don’t need to worry about moving and organising your source files within Xcode. Just create/move/rename files and re-run
xcodegen
.gitignore dance for Package.resolved
The docs are pretty good. There’s one thing to be careful of if you use SwiftPM because you’d want to check in Package.resolved
, but it’s in the project/workspace directories. So in git, you’d have to do this dance in .gitignore
if you use a project:
# xcodegen. Can't do only `*.xcodeproj` otherwise `Package.resolved` can't be made an exception as the directory isn't scanned
*.xcodeproj
*.xcworkspace/*
## We want the SwiftPM lock file
*.xcworkspace/xcshareddata/*
!*.xcworkspace/xcshareddata/
!*.xcworkspace/xcshareddata/swiftpm
!*.xcworkspace/xcshareddata/swiftpm/Package.resolved
and if you have a workspace (generally because you use CocoaPods; yes, you can mix SPM and CocoaPods):
# xcodegen. Can't do only `*.xcworkspace` otherwise `Package.resolved` can't be made an exception as the directory isn't scanned
*.xcodeproj
*.xcworkspace/*
## We want the SwiftPM lock file
*.xcworkspace/xcshareddata/*
!*.xcworkspace/xcshareddata/
!*.xcworkspace/xcshareddata/swiftpm
!*.xcworkspace/xcshareddata/swiftpm/Package.resolved