Skip to main content
Learn how to build release versions of your React Native app for iOS distribution via TestFlight or the App Store.

Overview

Building for iOS production creates an IPA (iOS App Store Package) file that can be:
  • Uploaded to TestFlight for beta testing
  • Submitted to the App Store for review and distribution
  • Distributed via Enterprise or Ad Hoc provisioning

Prerequisites

Building for iOS requires:
  • macOS with Xcode installed
  • Apple Developer account ($99/year)
  • Valid provisioning profiles and certificates
1

Install dependencies

cd ios
pod install
cd ..
2

Configure signing in Xcode

  1. Open ios/YourApp.xcworkspace in Xcode
  2. Select your project in the navigator
  3. Select your target
  4. Go to Signing & Capabilities
  5. Select your Team
  6. Choose appropriate Provisioning Profile

Building with Xcode

Archive for Distribution

1

Open workspace

open ios/YourApp.xcworkspace
2

Select scheme and device

  • In Xcode toolbar, select your scheme
  • Select Any iOS Device (arm64) as destination
3

Create archive

  1. Go to Product > Archive
  2. Wait for the build to complete
  3. Organizer window will open automatically
4

Distribute archive

  1. Select your archive
  2. Click Distribute App
  3. Choose distribution method:
    • App Store Connect - For TestFlight/App Store
    • Ad Hoc - For specific devices
    • Enterprise - For internal distribution
    • Development - For testing
  4. Follow the wizard to export IPA

Building with Command Line

Using xcodebuild

Build for Generic Device

cd ios

xcodebuild \
  -workspace YourApp.xcworkspace \
  -scheme YourApp \
  -configuration Release \
  -destination generic/platform=iOS \
  -archivePath ./build/YourApp.xcarchive \
  archive

Export IPA

xcodebuild \
  -exportArchive \
  -archivePath ./build/YourApp.xcarchive \
  -exportPath ./build \
  -exportOptionsPlist ExportOptions.plist

ExportOptions.plist

Create ios/ExportOptions.plist:
ios/ExportOptions.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>method</key>
    <string>app-store</string>
    <key>teamID</key>
    <string>YOUR_TEAM_ID</string>
    <key>uploadBitcode</key>
    <false/>
    <key>compileBitcode</key>
    <false/>
    <key>uploadSymbols</key>
    <true/>
    <key>signingStyle</key>
    <string>automatic</string>
</dict>
</plist>
Distribution methods:
  • app-store - For App Store Connect
  • ad-hoc - For specific registered devices
  • enterprise - For enterprise distribution
  • development - For development builds

Using Fastlane

Fastlane automates the entire build and distribution process.

Install Fastlane

sudo gem install fastlane
cd ios
fastlane init

Configure Fastfile

ios/fastlane/Fastfile
default_platform(:ios)

platform :ios do
  desc "Build and upload to TestFlight"
  lane :beta do
    increment_build_number(xcodeproj: "YourApp.xcodeproj")
    build_app(
      workspace: "YourApp.xcworkspace",
      scheme: "YourApp",
      export_method: "app-store"
    )
    upload_to_testflight(
      skip_waiting_for_build_processing: true
    )
  end
  
  desc "Build for App Store"
  lane :release do
    increment_build_number(xcodeproj: "YourApp.xcodeproj")
    build_app(
      workspace: "YourApp.xcworkspace",
      scheme: "YourApp",
      export_method: "app-store"
    )
    upload_to_app_store(
      submit_for_review: false,
      automatic_release: false
    )
  end
end

Run Fastlane

cd ios
fastlane beta    # Upload to TestFlight
fastlane release # Upload to App Store

Build Configurations

Debug vs Release

Debug:
  • Fast Refresh enabled
  • Developer menu available
  • Not optimized
  • Larger binary size
Release:
  • Optimized for performance
  • Smaller binary size
  • No developer tools
  • JavaScript bundled in app

Custom Configurations

Create custom configurations in Xcode:
1

Duplicate configuration

  1. Select project > Info tab
  2. Under Configurations, click +
  3. Select Duplicate “Release” Configuration
  4. Name it (e.g., “Staging”)
2

Create scheme

  1. Go to Product > Scheme > Manage Schemes
  2. Duplicate existing scheme
  3. Rename to match configuration
  4. Edit scheme > Build Configuration > Select “Staging”

Build with Custom Configuration

xcodebuild \
  -workspace YourApp.xcworkspace \
  -scheme YourApp-Staging \
  -configuration Staging \
  -destination generic/platform=iOS \
  archive

Code Signing

Automatic Signing

Recommended for most developers:
  1. In Xcode, select your target
  2. Signing & Capabilities tab
  3. Check Automatically manage signing
  4. Select your Team
Xcode handles provisioning profiles automatically.

Manual Signing

For advanced control:
  1. Uncheck Automatically manage signing
  2. Select Provisioning Profile for each configuration
  3. Ensure certificates are installed in Keychain

Certificates

You need:
  • Development Certificate - For debug builds
  • Distribution Certificate - For release builds
Manage at Apple Developer Portal.

Provisioning Profiles

  • Development - Testing on registered devices
  • Ad Hoc - Testing on up to 100 registered devices
  • App Store - For App Store distribution
  • Enterprise - For in-house distribution (requires Enterprise account)

Version Management

Update Version and Build Number

Via Xcode

  1. Select target > General tab
  2. Update Version (e.g., “1.2.0”)
  3. Update Build number (e.g., “42”)

Via Command Line

# Increment build number
cd ios
agvtool next-version -all

# Set version
agvtool new-marketing-version 1.2.0

Via Fastlane

fastlane run increment_version_number version_number:1.2.0
fastlane run increment_build_number

Version Requirements

  • Version (CFBundleShortVersionString): User-facing version (e.g., “1.2.0”)
  • Build (CFBundleVersion): Must be unique for each build uploaded to App Store Connect

Upload to App Store Connect

Using Xcode Organizer

  1. Product > Archive
  2. In Organizer, select archive
  3. Click Distribute App
  4. Choose App Store Connect
  5. Select Upload
  6. Follow wizard

Using Transporter App

  1. Download Transporter
  2. Open app
  3. Sign in with Apple ID
  4. Drag and drop IPA file
  5. Click Deliver

Using Command Line

xcrun altool --upload-app \
  --type ios \
  --file ./build/YourApp.ipa \
  --username "[email protected]" \
  --password "app-specific-password"
Generate app-specific password at appleid.apple.com.

Using Fastlane

fastlane deliver --ipa ./build/YourApp.ipa

Optimization

Reduce App Size

Enable Bitcode (if applicable)

ios/Podfile
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'YES'
    end
  end
end
Bitcode is no longer required for App Store submission as of Xcode 14.

App Thinning

App thinning is automatic when distributing via App Store Connect. The App Store delivers optimized versions to each device.

Remove Unused Assets

Use asset catalogs and remove unused images.

Optimization Settings

In Build Settings:
  • Optimization Level (Release): -Os or -O3
  • Strip Debug Symbols: YES
  • Strip Linked Product: YES
  • Make Strings Read-Only: YES
  • Dead Code Stripping: YES

Testing Release Build

Test Locally

Run release build on simulator:
npx react-native run-ios --configuration Release

TestFlight

Best way to test production builds:
  1. Upload build to App Store Connect
  2. Build processes automatically
  3. Add internal/external testers
  4. Testers install via TestFlight app

Continuous Integration

GitHub Actions

.github/workflows/ios.yml
name: iOS Build

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Install dependencies
        run: |
          npm install
          cd ios && pod install && cd ..
      
      - name: Build
        run: |
          cd ios
          xcodebuild \
            -workspace YourApp.xcworkspace \
            -scheme YourApp \
            -configuration Release \
            -destination generic/platform=iOS \
            -archivePath ./build/YourApp.xcarchive \
            archive
      
      - name: Export IPA
        run: |
          cd ios
          xcodebuild \
            -exportArchive \
            -archivePath ./build/YourApp.xcarchive \
            -exportPath ./build \
            -exportOptionsPlist ExportOptions.plist
      
      - name: Upload IPA
        uses: actions/upload-artifact@v3
        with:
          name: YourApp.ipa
          path: ios/build/YourApp.ipa

Using Fastlane in CI

- name: Build and upload to TestFlight
  env:
    MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
    FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.APP_STORE_CONNECT_PASSWORD }}
  run: |
    cd ios
    fastlane beta

Troubleshooting

Code Signing Issues

Error: No signing certificate found Solution:
  1. Ensure you’re logged into Xcode with Apple ID
  2. Download certificates from Developer Portal
  3. Install in Keychain Access

Provisioning Profile Errors

Error: No provisioning profile found Solution:
  • Use automatic signing in Xcode
  • Or download profile from Developer Portal
  • Install by double-clicking .mobileprovision file

Build Failed

Error: Various build errors Solution:
# Clean build folder
cd ios
rm -rf build
rm -rf Pods
pod install

# Clean in Xcode
# Product > Clean Build Folder (Cmd+Shift+K)

Archive Upload Failed

Error: This action could not be completed Solution:
  • Check App Store Connect status
  • Verify bundle ID matches your app
  • Ensure version/build number is unique
  • Try uploading via Transporter app

Missing Compliance

Error: Export compliance warning Solution: Add to Info.plist:
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
Or set to true and answer compliance questions in App Store Connect.

App Store Guidelines

Before submission, prepare:
  • App name and subtitle
  • Description
  • Keywords
  • Support URL
  • Privacy policy URL
  • Screenshots for all device sizes
  • App icon (1024x1024px)
  • Declare data collection practices
  • Include privacy policy
  • Request permissions with usage descriptions
  • Implement App Tracking Transparency if needed
Follow App Store Review Guidelines:
  • App must be complete and functional
  • No placeholder content
  • Accurate metadata
  • Proper use of APIs

Next Steps

Run iOS

Build and run on iOS devices

Publishing Guide

Complete guide to App Store submission

iOS Logs

Debug with iOS logs

App Signing

Deep dive into iOS code signing

Build docs developers (and LLMs) love