# iOS Release Skill
**Description**: Build and upload iOS apps to TestFlight for beta testing and App Store distribution.
## When to Use
- Releasing new iOS beta builds
- Submitting to the App Store
- Setting up CI/CD for iOS
- Managing iOS certificates and provisioning
## Prerequisites
### Required Tools
```bash
# Install Xcode Command Line Tools
xcode-select --install
# Install full Xcode from Mac App Store (required for iOS builds)
# Install CocoaPods
brew install cocoapods
```
### Apple Developer Account
1. Enroll in [Apple Developer Program](https://developer.apple.com/programs/)
2. Team ID: `748N7QPX7J` (example)
3. Bundle ID: `com.yourapp.yourapp`
## Fresh Setup
### 1. Configure Xcode
```bash
# Open Xcode → Settings → Accounts → + → Apple ID
# Sign in with your Apple Developer account
# Xcode auto-downloads provisioning profiles and certificates
```
### 2. Clone and Setup
```bash
git clone https://github.com/your-org/your-repo.git
cd your-repo/mobile_app/ios
pod install
cd ../..
```
## Build and Release Process
### 1. Update Build Number
The build number must be unique for each upload:
```bash
# Option 1: Let Cascade increment (recommended)
# The build number is in project.pbxproj under CURRENT_PROJECT_VERSION
# Option 2: Manual update
open mobile_app/ios/YourApp.xcodeproj
# Navigate to Target → General → Build
# Increment Build number (not Version)
```
### 2. Install Dependencies
```bash
cd mobile_app/ios && pod install && cd ../..
```
### 3. Clean Build Folder
```bash
xcodebuild clean \
-workspace mobile_app/ios/YourApp.xcworkspace \
-scheme YourApp \
-configuration Release
```
### 4. Archive the App
```bash
xcodebuild archive \
-workspace mobile_app/ios/YourApp.xcworkspace \
-scheme YourApp \
-configuration Release \
-archivePath build/YourApp.xcarchive \
-destination 'generic/platform=iOS' \
DEVELOPMENT_TEAM=YOUR_TEAM_ID \
CODE_SIGN_STYLE=Automatic
```
### 5. Export and Upload
```bash
xcodebuild -exportArchive \
-archivePath build/YourApp.xcarchive \
-exportPath build/export \
-exportOptionsPlist scripts/ExportOptions.plist
```
The `app-store-connect` export method auto-uploads to App Store Connect.
### 6. Configure in App Store Connect
1. Go to [App Store Connect](https://appstoreconnect.apple.com)
2. Navigate to My Apps → YourApp → TestFlight
3. Wait 5-15 minutes for processing
4. Add build to testing group:
- **Internal Testing**: Available immediately
- **External Testing**: Requires review (~24 hours)
## Alternative: Xcode GUI
1. Open `mobile_app/ios/YourApp.xcworkspace` (not `.xcodeproj`)
2. Select scheme: **YourApp**
3. Set destination: **Any iOS Device**
4. Product → Archive
5. In Organizer window: Distribute App → App Store Connect → Upload
## Key Configuration Files
### ExportOptions.plist
```xml
method
app-store-connect
teamID
YOUR_TEAM_ID
uploadBitcode
uploadSymbols
```
### Podfile
```ruby
platform :ios, '15.0'
target 'YourApp' do
use_frameworks!
# Azure Speech SDK
pod 'AzureSpeech', '~> 1.0'
target 'YourAppTests' do
inherit! :search_paths
end
end
```
## Build Configuration
| Setting | Value | Location |
| ----------------- | --------------------- | ------------------------------- |
| Team ID | `748N7QPX7J` | Xcode project settings |
| Bundle ID | `com.yourapp.yourapp` | Xcode project settings |
| Code Signing | Automatic | Target → Signing & Capabilities |
| Deployment Target | iOS 15.0+ | Podfile/Xcode project |
## CI/CD Integration
### GitHub Actions
```yaml
name: Build and Release iOS
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Install CocoaPods
run: |
cd mobile_app/ios
pod install
cd ../..
- name: Build Archive
env:
DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }}
run: |
xcodebuild archive \
-workspace mobile_app/ios/YourApp.xcworkspace \
-scheme YourApp \
-configuration Release \
-archivePath build/YourApp.xcarchive \
-destination 'generic/platform=iOS' \
DEVELOPMENT_TEAM=$DEVELOPMENT_TEAM \
CODE_SIGN_STYLE=Automatic
- name: Export and Upload
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
xcodebuild -exportArchive \
-archivePath build/YourApp.xcarchive \
-exportPath build/export \
-exportOptionsPlist scripts/ExportOptions.plist
```
## Troubleshooting
### Common Issues and Solutions
| Problem | Solution |
| ----------------------------- | ------------------------------------------------------------------------ |
| "No signing certificate" | Xcode → Settings → Accounts → Manage Certificates → + Apple Distribution |
| "Provisioning profile" error | Xcode → Target → Signing → Enable "Automatically manage signing" |
| "Build number already exists" | Increment build number in Xcode project |
| Upload stuck at "Processing" | Check [Apple System Status](https://developer.apple.com/system-status/) |
| "Invalid bundle" | Verify Bundle ID matches App Store Connect |
| Pod install fails | Run `pod deintegrate` then `pod install` |
| Archive fails | Clean build folder, check for linking errors |
### Debug Commands
```bash
# Validate app before upload
xcrun altool --validate-app \
-f build/export/YourApp.ipa \
-t ios \
-u your@email.com \
-p @keychain:AC_PASSWORD
# Check upload status
xcrun altool --notarization-info \
-u your@email.com \
-p @keychain:AC_PASSWORD
# List available provisioning profiles
ls ~/Library/MobileDevice/Provisioning\ Profiles/
```
## Best Practices
### Version Management
- Use semantic versioning: `MAJOR.MINOR.PATCH`
- Increment build number for every upload
- Keep release notes in App Store Connect
### Testing Before Release
1. **Internal Testing** - Test with team first
2. **External Testing** - Select beta testers
3. **TestFlight Groups** - Organize testers by type
4. **Feedback Collection** - Use TestFlight feedback
### Release Checklist
- [ ] Build number incremented
- [ ] All tests passing
- [ ] Release notes written
- [ ] Screenshots updated (all device sizes)
- [ ] App metadata current
- [ ] Privacy policy updated
- [ ] Age rating appropriate
- [ ] In-app purchases configured (if applicable)
## App Store Submission
### From TestFlight to Production
1. Ensure TestFlight build is stable
2. Create new app version in App Store Connect
3. Select build from TestFlight
4. Complete app review information
5. Submit for Review
### Review Process
- **Average time**: 24-48 hours
- **Common rejections**: Metadata issues, crashes, guideline violations
- **Expedited review**: Available for critical bug fixes
## Notes
- **Always test on real devices** - Simulators can miss issues
- **Keep certificates secure** - Never commit .p12 files
- **Monitor expiration dates** - Certificates expire annually
- **Use app-specific passwords** - For Apple ID authentication
- **Backup provisioning profiles** - Export from Xcode
## Related Skills
- [Generate Store Assets](./generate-store-assets.md) - Create required screenshots
- [Mobile Code Quality](./mobile-code-quality.md) - Before release
- [Desktop Release](./desktop-release.md) - Cross-platform releases
- [Test iOS App](./test-ios-app.md) - Local testing