swiftui-simulator-ui

📁 vladimirbrejcha/ios-ai-skills 📅 13 days ago
4
总安装量
1
周安装量
#53353
全站排名
安装命令
npx skills add https://github.com/vladimirbrejcha/ios-ai-skills --skill swiftui-simulator-ui

Agent 安装分布

opencode 1
cursor 1
codex 1
antigravity 1

Skill 文档

SwiftUI Simulator UI Feedback Loop

Build, run, and capture SwiftUI apps in iOS Simulator for visual verification. This skill enables AI agents to see what their UI code produces.

When to Use This Skill

Use this skill when:

  • Building or modifying SwiftUI views and need visual verification
  • Reviewing UI layouts, spacing, colors, or typography
  • Validating designs against specifications
  • Debugging visual issues (clipping, alignment, overlapping)
  • Capturing screenshots for documentation or handoffs
  • Testing different device sizes or appearances (dark mode, Dynamic Type)

Prerequisites

Before starting:

  1. Xcode installed with iOS Simulator support
  2. Project builds successfully (run xcodebuild -list to verify)
  3. At least one iOS Simulator available (xcrun simctl list devices available)

Quick Start (5-Step Workflow)

Step 1: Find Your Project Structure

# For .xcworkspace (if using CocoaPods/SPM packages)
xcodebuild -workspace /path/to/App.xcworkspace -list

# For .xcodeproj
xcodebuild -project /path/to/App.xcodeproj -list

# Output shows available schemes - pick the one you want to run

Step 2: Find Available Simulators

# List available iPhone simulators
xcrun simctl list devices available | grep iPhone

# Get UDID for a specific device (e.g., iPhone 16)
xcrun simctl list devices available | sed -nE '/iPhone 16/{s/.*\(([A-F0-9-]+)\).*/\1/p; q;}'

Step 3: Build the App

# Set your variables
PROJECT_PATH="/path/to/App.xcodeproj"  # or .xcworkspace
SCHEME="YourScheme"
DEVICE_NAME="iPhone 16"
DERIVED_DATA="/tmp/MyAppBuild"

# Get UDID
UDID=$(xcrun simctl list devices available | sed -nE "/$DEVICE_NAME/{s/.*\(([A-F0-9-]+)\).*/\1/p; q;}")

# Build
xcodebuild \
  -project "$PROJECT_PATH" \
  -scheme "$SCHEME" \
  -destination "platform=iOS Simulator,id=$UDID" \
  -derivedDataPath "$DERIVED_DATA" \
  build

Step 4: Install and Launch

# Find the built .app
APP_PATH=$(find "$DERIVED_DATA" -name "*.app" -type d | head -1)

# Boot simulator if needed
xcrun simctl boot "$UDID" 2>/dev/null || true

# Install
xcrun simctl install "$UDID" "$APP_PATH"

# Launch (get bundle ID from Info.plist or build settings)
BUNDLE_ID="com.example.yourapp"
xcrun simctl launch "$UDID" "$BUNDLE_ID"

Step 5: Capture Screenshot

# Create output directory
mkdir -p /tmp/UIScreenshots

# Take screenshot
xcrun simctl io "$UDID" screenshot "/tmp/UIScreenshots/screenshot-$(date +%Y%m%d-%H%M%S).png"

# The path is printed - use this to view the screenshot

Complete Workflow Script

Copy and adapt this script for your project:

#!/usr/bin/env bash
set -euo pipefail

# ============ CONFIGURATION (EDIT THESE) ============
PROJECT_PATH="${PROJECT_PATH:-/path/to/App.xcodeproj}"  # or .xcworkspace
SCHEME="${SCHEME:-YourScheme}"
BUNDLE_ID="${BUNDLE_ID:-com.example.yourapp}"
DEVICE_NAME="${DEVICE_NAME:-iPhone 16}"
DERIVED_DATA="${DERIVED_DATA:-/tmp/AppBuild}"
SCREENSHOT_DIR="${SCREENSHOT_DIR:-/tmp/UIScreenshots}"
# ====================================================

# Resolve simulator UDID
resolve_udid() {
  xcrun simctl list devices available | sed -nE "/$1/{s/.*\(([A-F0-9-]+)\).*/\1/p; q;}"
}

UDID=$(resolve_udid "$DEVICE_NAME")
if [[ -z "$UDID" ]]; then
  echo "error: Simulator '$DEVICE_NAME' not found. Available devices:"
  xcrun simctl list devices available | grep iPhone
  exit 1
fi

echo "Using simulator: $DEVICE_NAME ($UDID)"

# Boot simulator
if ! xcrun simctl list devices booted | grep -q "$UDID"; then
  echo "Booting simulator..."
  xcrun simctl boot "$UDID" 2>/dev/null || true
  sleep 2
fi

# Build
echo "Building..."
xcodebuild \
  -project "$PROJECT_PATH" \
  -scheme "$SCHEME" \
  -destination "platform=iOS Simulator,id=$UDID" \
  -derivedDataPath "$DERIVED_DATA" \
  -quiet \
  build

# Find app
APP_PATH=$(find "$DERIVED_DATA" -name "*.app" -type d | head -1)
if [[ ! -d "$APP_PATH" ]]; then
  echo "error: Built app not found in $DERIVED_DATA"
  exit 1
fi

# Install
echo "Installing..."
xcrun simctl install "$UDID" "$APP_PATH"

# Terminate if running, then launch
xcrun simctl terminate "$UDID" "$BUNDLE_ID" 2>/dev/null || true
xcrun simctl launch "$UDID" "$BUNDLE_ID"

echo "Launched $SCHEME on $DEVICE_NAME"

# Screenshot
mkdir -p "$SCREENSHOT_DIR"
SCREENSHOT_PATH="$SCREENSHOT_DIR/$(date +%Y%m%d-%H%M%S).png"
sleep 1  # Wait for app to render
xcrun simctl io "$UDID" screenshot "$SCREENSHOT_PATH"

echo "Screenshot saved: $SCREENSHOT_PATH"

Advanced Patterns

Pattern 1: Navigate to Specific Screen via Deep Link

# Launch app with deep link
xcrun simctl openurl "$UDID" "yourapp://settings/profile"

# Wait and screenshot
sleep 1
xcrun simctl io "$UDID" screenshot /tmp/profile-screen.png

Pattern 2: Configure App State via UserDefaults

# Write defaults before launch
xcrun simctl spawn "$UDID" defaults write "$BUNDLE_ID" ShowOnboarding -bool false
xcrun simctl spawn "$UDID" defaults write "$BUNDLE_ID" DebugMode -bool true
xcrun simctl spawn "$UDID" defaults write "$BUNDLE_ID" MockUserName -string "Test User"

# Terminate and relaunch to pick up changes
xcrun simctl terminate "$UDID" "$BUNDLE_ID"
xcrun simctl launch "$UDID" "$BUNDLE_ID"

Pattern 3: Test Different Appearances

# Enable dark mode
xcrun simctl ui "$UDID" appearance dark
sleep 0.5
xcrun simctl io "$UDID" screenshot /tmp/dark-mode.png

# Enable light mode
xcrun simctl ui "$UDID" appearance light
sleep 0.5
xcrun simctl io "$UDID" screenshot /tmp/light-mode.png

Pattern 4: Override Status Bar for Clean Screenshots

# Set time to 9:41, full battery, WiFi
xcrun simctl status_bar "$UDID" override \
  --time "9:41" \
  --batteryLevel 100 \
  --batteryState charged \
  --dataNetwork wifi \
  --wifiBars 3

xcrun simctl io "$UDID" screenshot /tmp/clean-screenshot.png

# Clear overrides
xcrun simctl status_bar "$UDID" clear

Pattern 5: Test Multiple Device Sizes

# Test on different devices
for DEVICE in "iPhone SE (3rd generation)" "iPhone 16" "iPhone 16 Pro Max"; do
  UDID=$(xcrun simctl list devices available | sed -nE "/$DEVICE/{s/.*\(([A-F0-9-]+)\).*/\1/p; q;}")
  if [[ -n "$UDID" ]]; then
    xcrun simctl boot "$UDID" 2>/dev/null || true
    xcrun simctl install "$UDID" "$APP_PATH"
    xcrun simctl launch "$UDID" "$BUNDLE_ID"
    sleep 2
    xcrun simctl io "$UDID" screenshot "/tmp/${DEVICE// /-}.png"
    xcrun simctl shutdown "$UDID"
  fi
done

Pattern 6: Preview Lab Target (Isolated UI Testing)

Create a dedicated target for UI preview:

// In a PreviewLab target
@main
struct PreviewLabApp: App {
    var body: some Scene {
        WindowGroup {
            // Show specific view based on launch argument
            switch ProcessInfo.processInfo.environment["PREVIEW_VIEW"] {
            case "settings":
                SettingsView()
            case "profile":
                ProfileView()
            default:
                ContentView()
            }
        }
    }
}

Launch with environment:

# Set environment variable
xcrun simctl spawn "$UDID" launchctl setenv PREVIEW_VIEW settings

# Launch
xcrun simctl launch "$UDID" "$BUNDLE_ID"

Pattern 7: Record Video of Interaction

# Start recording in background
xcrun simctl io "$UDID" recordVideo /tmp/recording.mp4 &
RECORD_PID=$!

# Wait for interaction (or interact manually)
sleep 5

# Stop recording
kill -INT $RECORD_PID

Finding Bundle ID

If you don’t know the bundle ID:

# From build settings
xcodebuild -project "$PROJECT_PATH" -scheme "$SCHEME" -showBuildSettings | grep PRODUCT_BUNDLE_IDENTIFIER

# From installed app
xcrun simctl listapps "$UDID" | grep -A1 CFBundleIdentifier

# From .app Info.plist after build
/usr/libexec/PlistBuddy -c "Print CFBundleIdentifier" "$APP_PATH/Info.plist"

Troubleshooting

Build Fails: “No matching destination”

# Check available destinations
xcodebuild -project "$PROJECT_PATH" -scheme "$SCHEME" -showDestinations

# Use exact simulator name from list
xcrun simctl list devices available

Simulator Won’t Boot

# Check current state
xcrun simctl list devices | grep -A5 "== Devices =="

# Force shutdown and reboot
xcrun simctl shutdown "$UDID"
xcrun simctl boot "$UDID"

# If still failing, reset simulator
xcrun simctl erase "$UDID"

App Won’t Install

# Check if app is built correctly
ls -la "$APP_PATH"

# Check architecture (must be x86_64 or arm64 for sim)
file "$APP_PATH/$(basename "$APP_PATH" .app)"

# Check minimum deployment target
/usr/libexec/PlistBuddy -c "Print MinimumOSVersion" "$APP_PATH/Info.plist"

Screenshot Shows Wrong Simulator

When multiple simulators are booted:

# List booted simulators
xcrun simctl list devices booted

# Always specify UDID explicitly
xcrun simctl io "$UDID" screenshot /tmp/screenshot.png

# Or shutdown other simulators
xcrun simctl shutdown all
xcrun simctl boot "$UDID"

App Launches but UI Doesn’t Load

# Check console output
xcrun simctl launch --console "$UDID" "$BUNDLE_ID"

# Stream logs
xcrun simctl spawn "$UDID" log stream --predicate 'processImagePath CONTAINS "YourApp"' --level debug

Screenshot is Black

# Wait longer for app to render
sleep 2
xcrun simctl io "$UDID" screenshot /tmp/screenshot.png

# Ensure simulator window is visible (not minimized)
# Or run in headless mode properly

Environment Variables Reference

Variable Description Default
PROJECT_PATH Path to .xcodeproj or .xcworkspace Required
SCHEME Xcode build scheme Required
BUNDLE_ID App bundle identifier Required
DEVICE_NAME Simulator device name iPhone 16
DEVICE_UDID Specific simulator UDID Auto-resolved
DERIVED_DATA Build output directory /tmp/AppBuild
SCREENSHOT_DIR Screenshot output directory /tmp/UIScreenshots

Detailed References

  • references/simulator-commands.md – Complete xcrun simctl command reference
  • references/xcodebuild-patterns.md – Build patterns and configurations
  • references/troubleshooting.md – Extended troubleshooting guide
  • assets/run_app.sh – Reusable run script template
  • assets/screenshot.sh – Standalone screenshot script

Integration with Handoffs

When using this skill for UI work:

  1. Run the UI feedback loop after making changes
  2. Capture a screenshot
  3. Include the screenshot path in your handoff file
  4. Example handoff entry:
## Progress

- [x] Implemented ProfileView header
- Screenshot: `/tmp/UIScreenshots/20250131-143022.png`
- Notes: Layout matches spec, tested on iPhone 16 and iPhone SE

Key Principles

  1. Always verify visually – Don’t assume UI code is correct; run it and see
  2. Use consistent device – Pick one simulator and stick with it for consistency
  3. Clean screenshots – Override status bar for professional captures
  4. Test edge cases – Dark mode, small screens, Dynamic Type
  5. Document with screenshots – Include paths in handoffs for traceability