I am a big fan of automation in software development so when I started doing iOS development one of my goals was to automate everything on the iOS project.
No more manual versioning, manual build distribution… let the computers do the work for me. Here is the setup I ended up with.
Separate app ids for development and distribution
Let’s say your app id is com.company.app. You can use that app id when developing the app, running it in the simulator or on your device and also when distribution the app using services like TestFlight or uploading it to the AppStore.
With just one app id you cannot have both the AppStore version and a development version installed on your device. This a problem when working on an app that you use daily for communication with your colleagues, but you are working on a feature that requires you to use a different server, or some MDM, etc.
There is also another problem you will encounter if you use push notifications. When you create a push notification certificate for production, push notifications for your app will work with AppStore builds, with ad-hoc builds in TestFlight and other services but you will not get any notifications when running the app on your device deployed from Xcode. At least not easily.
To counter that, I use separate app ids
- com.company.app with push notifications set to production for AppStore and ad-hoc distribution
- com.company.app.dev with push notifications set to sandbox for development
This of course requires your backend to support it by choosing the right push notifications certificate depending on the app id.
With this setup, I can
- use the AppStore version and the development version of the app on my device at the same time
- have push notifications working also in the development version of the app
Automatic builds and tests with Gitlab
The iOS project I work on uses self-hosted Gitlab instance, so using Gitlab CI was the obvious choice. You just need a machine with macOS that is always online, install the Gitlab runner, connect it to the Gitlab instance and you are done. Everything else is just a matter of configuration in a file in your repository.[Read More]