Skip to content

iOS

iOS development requires a macOS environment and enrollment in the Apple Developer Program ($99/year) to deploy applications to physical devices and distribute through the App Store. This guide covers code signing, provisioning profiles, CI/CD setup, and best practices for building iOS applications at KBVE.

Our React Native iOS applications use Expo for streamlined development and deployment workflows, with custom native modules when needed for advanced features.

Apple’s code signing system ensures app integrity and prevents unauthorized modifications. All iOS apps must be signed before deployment to devices or the App Store.

  1. Apple Developer Account

    • Enroll at developer.apple.com
    • Cost: $99/year for individual or organization membership
    • Required for device testing and App Store distribution
  2. Development Environment

    • macOS with Xcode installed
    • Xcode Command Line Tools: xcode-select --install
    • CocoaPods: sudo gem install cocoapods
  3. Bundle Identifier

    • KBVE React Native App: com.kbve.app
    • Must match across Xcode project, provisioning profiles, and App Store Connect

iOS App Development Certificate

Used for testing on physical devices during development.

Terminal window
# Generate via Xcode (automatic)
# Or manually via Keychain Access → Certificate Assistant → Request from CA
# Export as .p12 (for CI/CD)
# Keychain Access → Right-click certificate → Export

Provisioning profiles link certificates, app IDs, and device UDIDs together.

TypeUse CaseDevice Registration
DevelopmentTesting on registered devicesRequired
Ad HocBeta testing outside TestFlightRequired (max 100 devices)
App StoreApp Store distributionNot required
Terminal window
# Export provisioning profile to base64
base64 -i profile.mobileprovision | pbcopy

Add these secrets to your repository for CI/CD workflows.

Secret NameDescriptionHow to Generate
APPLE_CERT_DATABase64-encoded .p12 certificatebase64 -i certificate.p12 | pbcopy
APPLE_CERT_PASSWORDPassword for .p12 fileSet when exporting certificate
PROVISIONING_PROFILE_DATABase64-encoded .mobileprovisionbase64 -i profile.mobileprovision | pbcopy

Our React Native iOS builds use GitHub Actions with macOS runners.

Located at .github/workflows/ci-react-native-ios.yml

For development and CI testing (no certificates required)

Terminal window
# Trigger via GitHub Actions
# task: build
# skip_signing: true

Produces unsigned simulator build (x86_64) for testing purposes.

The exportOptions.plist file controls how the IPA is packaged.

  • Directoryapps/kbve/kbve-react-native/
    • exportOptions.plist Configuration for App Store export
    • Directoryios/ Generated by Expo prebuild
      • Podfile CocoaPods dependencies
      • *.xcworkspace Xcode workspace

exportOptions.plist Template:

<?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>manual</string>
<key>provisioningProfiles</key>
<dict>
<key>com.kbve.app</key>
<string>YOUR_PROVISIONING_PROFILE_NAME</string>
</dict>
</dict>
</plist>
- name: Import signing certificate
env:
APPLE_CERT_DATA: ${{ secrets.APPLE_CERT_DATA }}
APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }}
run: |
# Create temporary keychain
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
KEYCHAIN_PASSWORD=$(uuidgen)
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# Import certificate
echo "$APPLE_CERT_DATA" | base64 --decode > certificate.p12
security import certificate.p12 \
-P "$APPLE_CERT_PASSWORD" \
-A \
-t cert \
-f pkcs12 \
-k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Install provisioning profile
env:
PROVISIONING_PROFILE_DATA: ${{ secrets.PROVISIONING_PROFILE_DATA }}
run: |
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
echo "$PROVISIONING_PROFILE_DATA" | base64 --decode > \
~/Library/MobileDevice/Provisioning\ Profiles/profile.mobileprovision
- name: Build signed app
run: |
xcodebuild \
-workspace *.xcworkspace \
-scheme "kbvereactnative" \
-configuration Release \
-sdk iphoneos \
-archivePath ./build/App.xcarchive \
archive
xcodebuild \
-exportArchive \
-archivePath ./build/App.xcarchive \
-exportPath ./build \
-exportOptionsPlist exportOptions.plist

Verify builds work locally before pushing to CI/CD.

Terminal window
# Navigate to React Native app
cd apps/kbve/kbve-react-native
# Generate iOS native project
npx expo prebuild --platform ios --clean
# Install CocoaPods dependencies
cd ios
pod install
# Build for simulator (unsigned)
xcodebuild \
-workspace *.xcworkspace \
-scheme kbvereactnative \
-configuration Release \
-sdk iphonesimulator \
build
# Build for device (requires signing)
xcodebuild \
-workspace *.xcworkspace \
-scheme kbvereactnative \
-configuration Release \
-sdk iphoneos \
-archivePath ./build/App.xcarchive \
archive

Symptoms: errSecInternalComponent or certificate errors during build

Solutions:

  • Verify APPLE_CERT_DATA is valid base64
  • Check certificate password matches APPLE_CERT_PASSWORD
  • Ensure certificate hasn’t expired (check in Apple Developer portal)

Symptoms: No profiles for 'com.kbve.app' were found

Solutions:

  • Ensure Bundle ID matches: com.kbve.app
  • Profile must include the signing certificate
  • Check profile hasn’t expired
  • Verify Team ID in exportOptions.plist matches certificate

Symptoms: Code signing is required for product type 'Application'

Solutions:

  • Check Team ID in exportOptions.plist
  • Verify provisioning profile name is correct
  • Ensure certificate and profile are properly installed in keychain
  • Review Xcode build settings for code signing configuration

Symptoms: pod install fails or missing native modules

Solutions:

Terminal window
# Clear CocoaPods cache
cd ios
pod cache clean --all
rm -rf Pods Podfile.lock
# Reinstall
pod install --repo-update

KBVE also builds iOS applications using Unreal Engine 5. The UE5 iOS pipeline shares the same Apple Developer infrastructure (certificates, provisioning profiles, Team ID) as React Native builds.

Key Differences from React Native:

  • Build System: UE5 uses UnrealBuildTool (UBT) instead of xcodebuild directly
  • Project Generation: Xcode project generated via GenerateProjectFiles.sh or UE5 Editor
  • Binary Size: UE5 apps significantly larger due to engine runtime
  • Shader Compilation: Metal shaders must be precompiled for iOS targets

The UE5 iOS CI/CD pipeline is currently under development. See Issue #12875 for tracking.

Planned Tasks:

  • Configure Xcode project for UE5 iOS builds
  • Adapt code signing for UnrealBuildTool
  • Create GitHub Actions workflow for iOS builds
  • Test build pipeline on macOS runner
  • Document UE5-specific iOS build process

Shared Infrastructure:

Both React Native and UE5 iOS builds use the same:

  • Apple Developer certificates (APPLE_CERT_DATA, APPLE_CERT_PASSWORD)
  • Provisioning profiles (PROVISIONING_PROFILE_DATA)
  • macOS GitHub Actions runners
  • Fastlane automation (optional)
Terminal window
# Generate Xcode project from .uproject
# (Run on macOS with UE5 installed)
/Path/To/UE_5.X/Engine/Build/BatchFiles/Mac/GenerateProjectFiles.sh \
-project="/Path/To/YourProject.uproject" \
-platforms=iOS
# Build via UnrealBuildTool
/Path/To/UE_5.X/Engine/Build/BatchFiles/RunUBT.sh \
YourProjectEditor iOS Development \
-project="/Path/To/YourProject.uproject"
# Package for distribution
/Path/To/UE_5.X/Engine/Build/BatchFiles/RunUAT.sh BuildCookRun \
-project="/Path/To/YourProject.uproject" \
-platform=iOS \
-clientconfig=Shipping \
-cook -stage -archive -package

React Native iOS Pipeline

Issue #12876 - CI/CD implementation tracking

UE5 iOS Builds

Issue #12875 - Shares Apple Developer setup

Expo iOS Builds

Expo iOS docs - Expo-specific build configuration

  1. Enroll in Apple Developer Program

  2. Generate Certificates

    • Create iOS Distribution Certificate
    • Export as .p12 with strong password
  3. Create Provisioning Profile

    • Use Bundle ID: com.kbve.app
    • Select App Store distribution type
    • Download and export to base64
  4. Configure GitHub Secrets

    • Add APPLE_CERT_DATA, APPLE_CERT_PASSWORD, PROVISIONING_PROFILE_DATA
    • Update exportOptions.plist with Team ID and profile name
  5. Test Build Workflow

    • Run with skip_signing: true first (unsigned)
    • Then test with skip_signing: false (signed)
  6. Optional: Setup Fastlane

    • Automate TestFlight uploads
    • Manage certificates and profiles via match