iOS App Release Process - A Beginner's Guide
When I first started iOS indie development, releasing apps was always overwhelming. Here's a simple and practical release process to help new developers avoid common pitfalls and successfully complete their first (and every subsequent) app release.

As an iOS indie developer, looking back at the chaos of my first app release brings back memories of stress and confusion. The release process itself isn't actually complex - it's mainly the small details that are easy to overlook, leading to various issues. Here I'm sharing a simple workflow that I currently use, especially suitable for beginners.
Why Have a Release Process
Initially, I thought releasing an app was simple: modify code → build → upload. Then my first attempt went sideways:
- Forgot to update version numbers: Forgot to change the Widget version number, build failed
- Bundle ID mistakes: Widget Bundle ID prefix was wrong, got errors
- Mixed up test versions: Couldn't tell which version was installed on the phone (especially after building directly from Xcode to device)
- Didn't know how to handle build failures: Whether to resubmit or overwrite the previous commit after fixing code
These are all minor issues, but they can be quite frustrating when they occur frequently. Having a simple checklist can avoid these problems.
Preparation
Xcode Cloud: Automated Building
I recommend using Xcode Cloud for automated building and testing. This way, after each code commit, Xcode Cloud will automatically package and upload to App Store Connect, saving a lot of hassle.
Reference: Xcode Cloud Official Documentation
Maintaining Two Versions Simultaneously
This is a pretty useful technique - I maintain two sets of configurations:
- Production Version: For releases, standard Bundle ID, used on main and release/* branches
- Beta Version: For development and testing, Bundle ID with
.betasuffix, app name with an asterisk (), used on develop and feature/ branches
The Beta version app name has an asterisk (*) because TestFlight installations show a dot prefix in the app name, but building directly from Xcode to device has no distinguishing marks, making it hard to quickly differentiate between production and Beta versions.
Also create two app records on App Store Connect - one for official releases and one for Beta testing.
Why do this?
Mainly to avoid overwriting the production version on your phone during testing, allowing you to have both versions installed for comparison.
For example:
- Production version:
com.yourcompany.yourapp - Beta version:
com.yourcompany.yourapp.beta
This way you can have both versions on your phone simultaneously, and since the Bundle IDs are different, their data is also independent (except when using App Group for shared data).
Release Process (6 Simple Steps)
Step 1: Prepare Release Version
1. Create Release Branch (Optional)
If you use git flow:
git flow release start v1.2.0
If you don't use git flow, just create a new branch from develop.
2. Check Version Configuration This is the most important step, check each one:
- Open Xcode → Project → Each Target → General
- Update Version field to new version number
- Check Bundle Identifier (remove
.betasuffix for release version) - Confirm Display Name is correct
3. Widget Bundle ID Check If you have Widgets, ensure their Bundle IDs are prefixed with the main app's:
Main App:
com.yourcompany.yourapp
Widget:com.yourcompany.yourapp.widget✅Widget Bundle Identifier must be prefixed with the main app's Bundle Identifier, otherwise you'll get "Embedded binary's bundle identifier is not prefixed with the parent app's bundle identifier" error.
4. Compile Test
Run CMD + B to compile and ensure there are no issues before continuing.
Step 2: App Store Connect Setup
- Log into App Store Connect
- Create new version entry (if not already created)
Step 3: Commit Code
5. Commit Changes
git add .
git cz
# Or if not using commitizen
git commit -m "build: release v1.2.0"
git push
Step 4: Build and Test
6. Wait for Build Completion If using Xcode Cloud, wait for build completion; if building manually, Archive and upload to App Store Connect.
7. TestFlight Testing Download the built version through TestFlight and test the complete app functionality on a real device.
Step 5: Wrap Up
8. Merge Code
If using git flow:
git flow release finish v1.2.0
If not using git flow, manually merge to main branch.
Step 6: Release
9. Complete App Store Connect Configuration
- Log back into App Store Connect
- Fill in update description
- Select build version
- Submit for review
10. Clean Up Development Branch If you use dual version configuration, remember to revert the development branch back to Beta version configuration.
git checkout develop
git revert xxx # Revert release version configuration changes
Common Issues
1. What to do when build fails?
- Configuration issues (version numbers, Bundle ID, etc.): Fix and use
git commit --amendto overwrite commit - Code issues: Normally commit new fix commits
2. Should I test every time?
Yes, it's recommended every time, even for minor updates. TestFlight is very convenient.
3. Version Number Management
All Targets (main app, Widget, extensions) should have consistent version numbers.
4. Bundle ID Configuration
If using dual version configuration, recommend using Xcode Configurations to manage instead of manual changes.
Recommended Tools
- Git Flow: Branch management, optional but very practical
- Git Commitizen: Standardized commit messages
- Xcode Cloud: Automated building, hassle-free
- Xcode Configurations: Managing different environment configurations
Final Thoughts
This workflow may look like several steps, but it's actually quite simple. The core is: check configuration → commit code → build and test → release for review.
Everyone's project situation is different, so you can adjust according to your needs. But the most important thing is to have a fixed process to avoid being flustered during each release.
Hope this beginner's guide helps those just starting iOS development to quickly familiarize themselves with the release process and spend more time on the product itself.