/

Xcode Integration

Protect your app automatically every time you Archive in Xcode. No changes to your source code — just a post-archive script.


Prerequisites

Install Shield iOS using one of the supported methods:

Bash
# Homebrew (recommended on macOS)
brew install bytehide/tap/shield-ios

# or pip
pip install bytehide-shield-ios

Automatic Setup

The fastest way — one command configures everything:

Bash
bash <(curl -sL https://raw.githubusercontent.com/bytehide/shield-ios/main/scripts/setup.sh)

This installs Shield, creates shield-ios.json, and adds the post-archive action automatically. See Automatic Setup for details.


Manual Setup (2 Steps)

1. Add Post-Archive Action

  1. Open your project in Xcode
  2. Go to Product > Scheme > Edit Scheme... (or Cmd+<)

Open Edit Scheme from the scheme selectorClick to expand

  1. Select Archive > Post-actions
  2. Click + > New Run Script Action

Add a New Run Script Action in Archive Post-actionsClick to expand

  1. Set "Provide build settings from" to your app target
  2. Paste:
Bash
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
shield-ios protect "$ARCHIVE_PATH" -o "$ARCHIVE_PATH" --no-sign

2. Add Configuration (optional)

For custom protections, create a shield-ios.json in your project root:

Bash
shield-ios init

Then update the post-archive script to use it:

Bash
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
shield-ios protect "$ARCHIVE_PATH" -o "$ARCHIVE_PATH" --config "${PROJECT_DIR}/shield-ios.json" --no-sign

That's it. Every time you Archive (Product > Archive), Shield protects your app automatically.

Post-archive action configured with Shield iOS scriptClick to expand


How It Works

--no-sign is used because Xcode handles code signing when you distribute from the Organizer or use xcodebuild -exportArchive.


Debug Build Integration

You can also protect your app during debug builds (Cmd+R) by adding a Run Script Build Phase. This lets you test protections with the Xcode debugger attached, so crash logs appear directly in the Xcode console.

Setup

  1. Open your project in Xcode
  2. Select your app target > Build Phases
  3. Click + > New Run Script Phase
  4. Drag it after "Compile Sources" and "Link Binary With Libraries"
  5. Paste:
Bash
if [ "$CONFIGURATION" = "Debug" ]; then
    export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
    shield-ios protect "$CODESIGNING_FOLDER_PATH" \
        -o "$CODESIGNING_FOLDER_PATH" \
        --config "${PROJECT_DIR}/shield-ios.json" \
        --no-sign
fi

How It Works

Important Notes

Disable anti_debug

When using Debug Build Integration, you must disable anti_debug in your debug configuration. Otherwise, the debugger won't be able to attach to the app.

Use a separate config for debug builds:

JSON
{
  "protections": {
    "anti_debug": false,
    "string_encryption": true,
    "symbol_renaming": true,
    "control_flow": "light"
  }
}
  • The $CONFIGURATION check ensures Shield only runs on Debug builds. Remove the if block to run on all configurations.
  • This modifies the .app in-place, with no temp files or repacking.
  • For a comprehensive guide on testing protected builds, see Debug & Testing.

CI/CD with xcodebuild

For automated builds, call shield-ios between archive and exportArchive:

Bash
# 1. Build the archive
xcodebuild archive \
  -project MyApp.xcodeproj \
  -scheme MyApp \
  -archivePath build/MyApp.xcarchive

# 2. Protect the archive
shield-ios protect build/MyApp.xcarchive \
  -o build/MyApp.xcarchive \
  --config shield-ios.json \
  --no-sign

# 3. Export to IPA (Xcode signs here)
xcodebuild -exportArchive \
  -archivePath build/MyApp.xcarchive \
  -exportOptionsPlist ExportOptions.plist \
  -exportPath build/output

Configuration

See Configuration Reference for all available protections and configuration options.

Example shield-ios.json:

JSON
{
  "projectToken": "bh_YOUR_TOKEN",
  "protections": {
    "anti_debug": true,
    "anti_jailbreak": true,
    "string_encryption": true,
    "symbol_renaming": true,
    "control_flow": "medium"
  }
}

Project Structure

CODE
MyApp/
├── MyApp.xcodeproj
├── MyApp/
│   ├── AppDelegate.swift
│   └── ...
└── shield-ios.json       <-- optional config

No extra scripts or build phases needed — just the post-archive action in your scheme.


Troubleshooting

"shield-ios: command not found" in Post-Archive Action

Xcode post-actions have a minimal PATH. Make sure the first line exports the correct paths:

Bash
export PATH="/opt/homebrew/bin:/usr/local/bin:$HOME/.local/bin:$PATH"

Check where shield-ios is installed:

Bash
which shield-ios

If you installed with a specific Python version:

Bash
export PATH="/opt/homebrew/bin:/usr/local/bin:$HOME/Library/Python/3.12/bin:$PATH"

Post-Archive Action doesn't run

  • Make sure "Provide build settings from" is set to your app target (not "None")
  • Post-actions only run on Archive (Product > Archive), not regular builds (Cmd+B)

"No .app found inside xcarchive"

The archive may have failed before producing a valid .app. Check that the archive step succeeds before Shield runs.

Protection seems to have no effect

  • Post-actions only run during Archive, not Debug/Run builds
  • To verify: add echo "Shield ran at $(date)" > /tmp/shield-check.txt to the post-action and check if the file appears

Code signing errors when distributing

Always use --no-sign in the post-archive action. Xcode handles signing when you distribute from Organizer or xcodebuild -exportArchive.


Next Steps

Configuration Reference

Full configuration options

Fastlane Plugin

CI/CD with Fastlane

CI/CD Integration

GitHub Actions, GitLab CI, and more

Previous
Fastlane Plugin