axiom-deep-link-debugging

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Deep Link Debugging

调试深度链接

When to Use This Skill

何时使用该技能

Use when:
  • Adding debug-only deep links for simulator testing
  • Enabling automated navigation to specific screens for screenshot/testing
  • Integrating with
    simulator-tester
    agent or
    /axiom:screenshot
  • Need to navigate programmatically without production deep link implementation
  • Testing navigation flows without manual tapping
Do NOT use for:
  • Production deep linking (use
    axiom-swiftui-nav
    skill instead)
  • Universal links or App Clips
  • Complex routing architectures
适用于以下场景:
  • 为模拟器测试添加仅调试用的深度链接
  • 实现自动跳转到特定页面以进行截图/测试
  • simulator-tester
    Agent 或
    /axiom:screenshot
    集成
  • 需要在不实现生产环境深度链接的情况下以编程方式跳转页面
  • 无需手动点击即可测试导航流程
请勿用于
  • 生产环境深度链接(请改用
    axiom-swiftui-nav
    技能)
  • Universal Links 或 App Clips
  • 复杂路由架构

Example Prompts

示例提示

1. "Claude Code can't navigate to specific screens for testing"

1. "Claude Code 无法跳转到特定页面进行测试"

→ Add debug-only URL scheme to enable
xcrun simctl openurl
navigation
→ 添加仅调试用的 URL Scheme,支持通过
xcrun simctl openurl
进行导航

2. "I want to take screenshots of different screens automatically"

2. "我想自动截取不同页面的截图"

→ Create debug deep links for each screen, callable from simulator
→ 为每个页面创建调试深度链接,可从模拟器调用

3. "Automated testing needs to set up specific app states"

3. "自动化测试需要设置特定的应用状态"

→ Add debug links that navigate AND configure state

→ 添加既能跳转又能配置状态的调试链接

Red Flags — When You Need Debug Deep Links

警示信号——你需要调试深度链接的场景

If you're experiencing ANY of these, add debug deep links:
Testing friction:
  • ❌ "I have to manually tap through 5 screens to test this feature"
  • ❌ "Screenshot capture can't show the screen I need to debug"
  • ❌ "Automated tests can't reach the error state without complex setup"
Debugging inefficiency:
  • ❌ "I make a fix, rebuild, manually navigate, check — takes 3 minutes per iteration"
  • ❌ "Can't visually verify fixes because Claude Code can't navigate there"
Solution: Add debug deep links that let you (and Claude Code) jump directly to any screen with any state configuration.

如果你遇到以下任何一种情况,就应该添加调试深度链接:
测试效率低下
  • ❌ "我必须手动点击5个页面才能测试这个功能"
  • ❌ "截图工具无法展示我需要调试的页面"
  • ❌ "自动化测试需要复杂的设置才能触发错误状态"
调试效率低下
  • ❌ "我修复问题后,需要重新构建、手动跳转、检查——每次迭代需要3分钟"
  • ❌ "无法直观验证修复效果,因为 Claude Code 无法跳转到对应页面"
解决方案:添加调试深度链接,让你(和 Claude Code)可以直接跳转到任意页面,并配置任意状态。

Implementation

实现方案

Pattern 1: Basic Debug URL Scheme (SwiftUI)

模式1:基础调试URL Scheme(SwiftUI)

Add a debug-only URL scheme that routes to screens.
swift
import SwiftUI

struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                #if DEBUG
                .onOpenURL { url in
                    handleDebugURL(url)
                }
                #endif
        }
    }

    #if DEBUG
    private func handleDebugURL(_ url: URL) {
        guard url.scheme == "debug" else { return }

        // Route based on host
        switch url.host {
        case "settings":
            // Navigate to settings
            NotificationCenter.default.post(
                name: .navigateToSettings,
                object: nil
            )

        case "profile":
            // Navigate to profile
            let userID = url.queryItems?["id"] ?? "current"
            NotificationCenter.default.post(
                name: .navigateToProfile,
                object: userID
            )

        case "reset":
            // Reset app to initial state
            resetApp()

        default:
            print("⚠️ Unknown debug URL: \(url)")
        }
    }
    #endif
}

#if DEBUG
extension Notification.Name {
    static let navigateToSettings = Notification.Name("navigateToSettings")
    static let navigateToProfile = Notification.Name("navigateToProfile")
}

extension URL {
    var queryItems: [String: String]? {
        guard let components = URLComponents(url: self, resolvingAgainstBaseURL: false),
              let items = components.queryItems else {
            return nil
        }
        return Dictionary(uniqueKeysWithValues: items.map { ($0.name, $0.value ?? "") })
    }
}
#endif
Usage:
bash
undefined
添加仅调试用的URL Scheme,用于路由到不同页面。
swift
import SwiftUI

struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                #if DEBUG
                .onOpenURL { url in
                    handleDebugURL(url)
                }
                #endif
        }
    }

    #if DEBUG
    private func handleDebugURL(_ url: URL) {
        guard url.scheme == "debug" else { return }

        // 根据host进行路由
        switch url.host {
        case "settings":
            // 跳转到设置页面
            NotificationCenter.default.post(
                name: .navigateToSettings,
                object: nil
            )

        case "profile":
            // 跳转到个人资料页面
            let userID = url.queryItems?["id"] ?? "current"
            NotificationCenter.default.post(
                name: .navigateToProfile,
                object: userID
            )

        case "reset":
            // 将应用重置为初始状态
            resetApp()

        default:
            print("⚠️ 未知调试URL: \(url)")
        }
    }
    #endif
}

#if DEBUG
extension Notification.Name {
    static let navigateToSettings = Notification.Name("navigateToSettings")
    static let navigateToProfile = Notification.Name("navigateToProfile")
}

extension URL {
    var queryItems: [String: String]? {
        guard let components = URLComponents(url: self, resolvingAgainstBaseURL: false),
              let items = components.queryItems else {
            return nil
        }
        return Dictionary(uniqueKeysWithValues: items.map { ($0.name, $0.value ?? "") })
    }
}
#endif
使用方式:
bash
undefined

From simulator

在模拟器中执行

xcrun simctl openurl booted "debug://settings" xcrun simctl openurl booted "debug://profile?id=123" xcrun simctl openurl booted "debug://reset"

---
xcrun simctl openurl booted "debug://settings" xcrun simctl openurl booted "debug://profile?id=123" xcrun simctl openurl booted "debug://reset"

---

Pattern 2: NavigationPath Integration (iOS 16+)

模式2:集成NavigationPath(iOS 16+)

Integrate debug deep links with NavigationStack for robust navigation.
swift
import SwiftUI

@MainActor
class DebugRouter: ObservableObject {
    @Published var path = NavigationPath()

    #if DEBUG
    func handleDebugURL(_ url: URL) {
        guard url.scheme == "debug" else { return }

        switch url.host {
        case "settings":
            path.append(Destination.settings)

        case "recipe":
            if let id = url.queryItems?["id"], let recipeID = Int(id) {
                path.append(Destination.recipe(id: recipeID))
            }

        case "recipe-edit":
            if let id = url.queryItems?["id"], let recipeID = Int(id) {
                // Navigate to recipe, then to edit
                path.append(Destination.recipe(id: recipeID))
                path.append(Destination.recipeEdit(id: recipeID))
            }

        case "reset":
            path = NavigationPath() // Pop to root

        default:
            print("⚠️ Unknown debug URL: \(url)")
        }
    }
    #endif
}

struct ContentView: View {
    @StateObject private var router = DebugRouter()

    var body: some View {
        NavigationStack(path: $router.path) {
            HomeView()
                .navigationDestination(for: Destination.self) { destination in
                    destinationView(for: destination)
                }
        }
        #if DEBUG
        .onOpenURL { url in
            router.handleDebugURL(url)
        }
        #endif
    }

    @ViewBuilder
    private func destinationView(for destination: Destination) -> some View {
        switch destination {
        case .settings:
            SettingsView()
        case .recipe(let id):
            RecipeDetailView(recipeID: id)
        case .recipeEdit(let id):
            RecipeEditView(recipeID: id)
        }
    }
}

enum Destination: Hashable {
    case settings
    case recipe(id: Int)
    case recipeEdit(id: Int)
}
Usage:
bash
undefined
将调试深度链接与NavigationStack集成,实现更可靠的导航。
swift
import SwiftUI

@MainActor
class DebugRouter: ObservableObject {
    @Published var path = NavigationPath()

    #if DEBUG
    func handleDebugURL(_ url: URL) {
        guard url.scheme == "debug" else { return }

        switch url.host {
        case "settings":
            path.append(Destination.settings)

        case "recipe":
            if let id = url.queryItems?["id"], let recipeID = Int(id) {
                path.append(Destination.recipe(id: recipeID))
            }

        case "recipe-edit":
            if let id = url.queryItems?["id"], let recipeID = Int(id) {
                // 先跳转到菜谱页面,再跳转到编辑页面
                path.append(Destination.recipe(id: recipeID))
                path.append(Destination.recipeEdit(id: recipeID))
            }

        case "reset":
            path = NavigationPath() // 返回根页面

        default:
            print("⚠️ 未知调试URL: \(url)")
        }
    }
    #endif
}

struct ContentView: View {
    @StateObject private var router = DebugRouter()

    var body: some View {
        NavigationStack(path: $router.path) {
            HomeView()
                .navigationDestination(for: Destination.self) { destination in
                    destinationView(for: destination)
                }
        }
        #if DEBUG
        .onOpenURL { url in
            router.handleDebugURL(url)
        }
        #endif
    }

    @ViewBuilder
    private func destinationView(for destination: Destination) -> some View {
        switch destination {
        case .settings:
            SettingsView()
        case .recipe(let id):
            RecipeDetailView(recipeID: id)
        case .recipeEdit(let id):
            RecipeEditView(recipeID: id)
        }
    }
}

enum Destination: Hashable {
    case settings
    case recipe(id: Int)
    case recipeEdit(id: Int)
}
使用方式:
bash
undefined

Navigate to settings

跳转到设置页面

xcrun simctl openurl booted "debug://settings"
xcrun simctl openurl booted "debug://settings"

Navigate to recipe #42

跳转到编号为42的菜谱页面

xcrun simctl openurl booted "debug://recipe?id=42"
xcrun simctl openurl booted "debug://recipe?id=42"

Navigate to recipe #42 edit screen

跳转到编号为42的菜谱编辑页面

xcrun simctl openurl booted "debug://recipe-edit?id=42"
xcrun simctl openurl booted "debug://recipe-edit?id=42"

Pop to root

返回根页面

xcrun simctl openurl booted "debug://reset"

---
xcrun simctl openurl booted "debug://reset"

---

Pattern 3: State Configuration Links

模式3:状态配置链接

Debug links that both navigate AND configure state.
swift
#if DEBUG
extension DebugRouter {
    func handleDebugURL(_ url: URL) {
        guard url.scheme == "debug" else { return }

        switch url.host {
        case "login":
            // Show login screen
            path.append(Destination.login)

        case "login-error":
            // Show login screen WITH error state
            path.append(Destination.login)
            // Trigger error state
            NotificationCenter.default.post(
                name: .showLoginError,
                object: "Invalid credentials"
            )

        case "recipe-empty":
            // Show recipe list in empty state
            UserDefaults.standard.set(true, forKey: "debug_emptyRecipeList")
            path.append(Destination.recipes)

        case "recipe-error":
            // Show recipe list with network error
            UserDefaults.standard.set(true, forKey: "debug_networkError")
            path.append(Destination.recipes)

        default:
            print("⚠️ Unknown debug URL: \(url)")
        }
    }
}
#endif
Usage:
bash
undefined
可同时实现页面跳转和状态配置的调试链接。
swift
#if DEBUG
extension DebugRouter {
    func handleDebugURL(_ url: URL) {
        guard url.scheme == "debug" else { return }

        switch url.host {
        case "login":
            // 展示登录页面
            path.append(Destination.login)

        case "login-error":
            // 展示带错误状态的登录页面
            path.append(Destination.login)
            // 触发错误状态
            NotificationCenter.default.post(
                name: .showLoginError,
                object: "无效凭据"
            )

        case "recipe-empty":
            // 展示空状态的菜谱列表
            UserDefaults.standard.set(true, forKey: "debug_emptyRecipeList")
            path.append(Destination.recipes)

        case "recipe-error":
            // 展示带网络错误的菜谱列表
            UserDefaults.standard.set(true, forKey: "debug_networkError")
            path.append(Destination.recipes)

        default:
            print("⚠️ 未知调试URL: \(url)")
        }
    }
}
#endif
使用方式:
bash
undefined

Test login error state

测试登录错误状态

xcrun simctl openurl booted "debug://login-error"
xcrun simctl openurl booted "debug://login-error"

Test empty recipe list

测试空菜谱列表状态

xcrun simctl openurl booted "debug://recipe-empty"
xcrun simctl openurl booted "debug://recipe-empty"

Test network error handling

测试网络错误处理

xcrun simctl openurl booted "debug://recipe-error"

---
xcrun simctl openurl booted "debug://recipe-error"

---

Pattern 4: Info.plist Configuration (DEBUG only)

模式4:Info.plist配置(仅DEBUG环境)

Register the debug URL scheme ONLY in debug builds.
Step 1: Add scheme to Info.plist
xml
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>debug</string>
        </array>
        <key>CFBundleURLName</key>
        <string>com.example.debug</string>
    </dict>
</array>
Step 2: Strip from release builds
Add a Run Script phase to your target's Build Phases (runs BEFORE "Copy Bundle Resources"):
bash
undefined
仅在调试构建中注册调试URL Scheme。
步骤1:向Info.plist中添加Scheme
xml
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>debug</string>
        </array>
        <key>CFBundleURLName</key>
        <string>com.example.debug</string>
    </dict>
</array>
步骤2:在发布构建中移除该Scheme
在Target的Build Phases中添加一个Run Script阶段(在"Copy Bundle Resources"之前执行):
bash
undefined

Strip debug URL scheme from Release builds

在Release构建中移除调试URL Scheme

if [ "${CONFIGURATION}" = "Release" ]; then echo "Removing debug URL scheme from Info.plist"
/usr/libexec/PlistBuddy -c "Delete :CFBundleURLTypes:0" "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}" 2>/dev/null || true
fi

**Alternative**: Use separate Info.plist files for Debug vs Release configurations in Build Settings.

---
if [ "${CONFIGURATION}" = "Release" ]; then echo "Removing debug URL scheme from Info.plist"
/usr/libexec/PlistBuddy -c "Delete :CFBundleURLTypes:0" "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}" 2>/dev/null || true
fi

**替代方案**:在Build Settings中为Debug和Release配置使用不同的Info.plist文件。

---

Integration with Simulator Testing

与模拟器测试的集成

With
/axiom:screenshot
Command

/axiom:screenshot
命令配合使用

bash
undefined
bash
undefined

1. Navigate to screen

1. 跳转到目标页面

xcrun simctl openurl booted "debug://settings"
xcrun simctl openurl booted "debug://settings"

2. Wait for navigation

2. 等待页面跳转完成

sleep 1
sleep 1

3. Capture screenshot

3. 截取屏幕截图

/axiom:screenshot
undefined
/axiom:screenshot
undefined

With
simulator-tester
Agent

simulator-tester
Agent配合使用

Simply tell the agent:
  • "Navigate to Settings and take a screenshot"
  • "Open the recipe editor and verify the layout"
  • "Go to the error state and show me what it looks like"
The agent will use your debug deep links to navigate.

只需告知Agent:
  • "跳转到设置页面并截图"
  • "打开菜谱编辑器并验证布局"
  • "进入错误状态并展示效果"
Agent会使用你的调试深度链接进行页面跳转。

Mandatory First Steps

必须完成的前置步骤

ALWAYS complete these steps before adding debug deep links:
在添加调试深度链接之前,请务必完成以下步骤

Step 1: Define Navigation Needs

步骤1:明确导航需求

List all screens you need to reach for testing:
- Settings screen
- Profile screen (with specific user ID)
- Recipe detail (with specific recipe ID)
- Error states (login error, network error, etc.)
- Empty states (no recipes, no favorites)
列出所有需要通过测试访问的页面:
- 设置页面
- 个人资料页面(带指定用户ID)
- 菜谱详情页面(带指定菜谱ID)
- 错误状态(登录错误、网络错误等)
- 空状态(无菜谱、无收藏等)

Step 2: Choose URL Scheme Pattern

步骤2:选择URL Scheme格式

debug://screen-name              # Simple screen navigation
debug://screen-name?param=value  # Navigation with parameters
debug://state-name               # State configuration
debug://页面名称              # 简单页面跳转
debug://页面名称?参数=值  # 带参数的页面跳转
debug://状态名称               # 状态配置

Step 3: Add URL Handler

步骤3:添加URL处理器

Use
#if DEBUG
to ensure code is stripped from release builds.
使用
#if DEBUG
确保代码不会被包含在发布构建中。

Step 4: Test Deep Links

步骤4:测试深度链接

bash
undefined
bash
undefined

Boot simulator

启动模拟器

xcrun simctl boot "iPhone 16 Pro"
xcrun simctl boot "iPhone 16 Pro"

Launch app

启动应用

xcrun simctl launch booted com.example.YourApp
xcrun simctl launch booted com.example.YourApp

Test each deep link

测试每个深度链接

xcrun simctl openurl booted "debug://settings" xcrun simctl openurl booted "debug://profile?id=123"

---
xcrun simctl openurl booted "debug://settings" xcrun simctl openurl booted "debug://profile?id=123"

---

Common Mistakes

常见错误

❌ WRONG — Hardcoding navigation in URL handler

❌ 错误示例——在URL处理器中硬编码导航逻辑

swift
#if DEBUG
func handleDebugURL(_ url: URL) {
    if url.host == "settings" {
        // ❌ WRONG — Creates tight coupling
        self.showingSettings = true
    }
}
#endif
Problem: URL handler now owns navigation logic, duplicating coordinator/router patterns.
✅ RIGHT — Use existing navigation system:
swift
#if DEBUG
func handleDebugURL(_ url: URL) {
    if url.host == "settings" {
        // Use existing NavigationPath
        path.append(Destination.settings)
    }
}
#endif

swift
#if DEBUG
func handleDebugURL(_ url: URL) {
    if url.host == "settings" {
        // ❌ 错误——造成强耦合
        self.showingSettings = true
    }
}
#endif
问题:URL处理器现在拥有导航逻辑,与协调器/路由模式重复。
✅ 正确示例——使用现有导航系统:
swift
#if DEBUG
func handleDebugURL(_ url: URL) {
    if url.host == "settings" {
        // 使用现有的NavigationPath
        path.append(Destination.settings)
    }
}
#endif

❌ WRONG — Leaving debug code in production

❌ 错误示例——将调试代码留在生产环境中

swift
// ❌ WRONG — No #if DEBUG
func handleDebugURL(_ url: URL) {
    // This ships to users!
}
Problem: Debug endpoints exposed in production. Security risk.
✅ RIGHT — Wrap in #if DEBUG:
swift
#if DEBUG
func handleDebugURL(_ url: URL) {
    // Stripped from release builds
}
#endif

swift
// ❌ 错误——未使用#if DEBUG
func handleDebugURL(_ url: URL) {
    // 这段代码会被发布给用户!
}
问题:调试端点暴露在生产环境中,存在安全风险。
✅ 正确示例——用#if DEBUG包裹:
swift
#if DEBUG
func handleDebugURL(_ url: URL) {
    // 不会被包含在发布构建中
}
#endif

❌ WRONG — Using query parameters without validation

❌ 错误示例——未验证查询参数

swift
#if DEBUG
case "profile":
    let userID = Int(url.queryItems?["id"] ?? "0")! // ❌ Force unwrap
    path.append(Destination.profile(id: userID))
#endif
Problem: Crashes if
id
is missing or invalid.
✅ RIGHT — Validate parameters:
swift
#if DEBUG
case "profile":
    guard let idString = url.queryItems?["id"],
          let userID = Int(idString) else {
        print("⚠️ Invalid profile ID")
        return
    }
    path.append(Destination.profile(id: userID))
#endif

swift
#if DEBUG
case "profile":
    let userID = Int(url.queryItems?["id"] ?? "0")! // ❌ 强制解包
    path.append(Destination.profile(id: userID))
#endif
问题:如果
id
缺失或无效,会导致崩溃。
✅ 正确示例——验证参数:
swift
#if DEBUG
case "profile":
    guard let idString = url.queryItems?["id"],
          let userID = Int(idString) else {
        print("⚠️ 无效的用户ID")
        return
    }
    path.append(Destination.profile(id: userID))
#endif

Testing Checklist

测试检查清单

Before using debug deep links in automated workflows:
  • URL handler wrapped in
    #if DEBUG
  • All deep links tested manually in simulator
  • Parameters validated (don't force unwrap)
  • Deep links integrate with existing navigation (don't duplicate logic)
  • URL scheme stripped from Release builds (script or separate Info.plist)
  • Documented in README or comments for other developers
  • Works with
    /axiom:screenshot
    command
  • Works with
    simulator-tester
    agent

在将调试深度链接用于自动化流程之前,请检查以下内容:
  • URL处理器已用
    #if DEBUG
    包裹
  • 所有深度链接已在模拟器中手动测试
  • 参数已验证(不使用强制解包)
  • 深度链接与现有导航系统集成(不重复逻辑)
  • URL Scheme已从Release构建中移除(通过脚本或单独的Info.plist)
  • 已在README或注释中为其他开发者文档化
  • 可与
    /axiom:screenshot
    命令配合使用
  • 可与
    simulator-tester
    Agent配合使用

Real-World Example

实际场景示例

Scenario: You're debugging a recipe app layout issue in the editor screen.
Before (manual testing):
  1. Build app → 30 seconds
  2. Launch simulator
  3. Tap "Recipes" → wait for load
  4. Scroll to recipe #42
  5. Tap to open detail
  6. Tap "Edit"
  7. Check if layout is fixed
  8. Make change, rebuild → repeat from step 1 Total: 2-3 minutes per iteration
After (with debug deep links):
  1. Build app → 30 seconds
  2. Run:
    xcrun simctl openurl booted "debug://recipe-edit?id=42"
  3. Run:
    /axiom:screenshot
  4. Claude analyzes screenshot and confirms layout fix
  5. Make change if needed, rebuild → repeat from step 2 Total: 45 seconds per iteration
Time savings: 60-75% faster iteration with visual verification

场景:你正在调试菜谱应用编辑器页面的布局问题。
之前(手动测试):
  1. 构建应用 → 30秒
  2. 启动模拟器
  3. 点击"菜谱" → 等待加载
  4. 滚动到编号为42的菜谱
  5. 点击打开详情页
  6. 点击"编辑"
  7. 检查布局是否修复
  8. 修改代码,重新构建 → 从步骤1重复 总耗时:每次迭代2-3分钟
之后(使用调试深度链接):
  1. 构建应用 → 30秒
  2. 执行:
    xcrun simctl openurl booted "debug://recipe-edit?id=42"
  3. 执行:
    /axiom:screenshot
  4. Claude分析截图并确认布局已修复
  5. 如有需要修改代码,重新构建 → 从步骤2重复 总耗时:每次迭代45秒
时间节省:视觉修复的迭代速度提升60-75%

Integration with Existing Navigation

与现有导航系统的集成

For Apps Using NavigationStack

对于使用NavigationStack的应用

Add debug URL handler that appends to existing NavigationPath:
swift
router.path.append(Destination.fromDebugURL(url))
添加调试URL处理器,将目标页面添加到现有的NavigationPath中:
swift
router.path.append(Destination.fromDebugURL(url))

For Apps Using Coordinator Pattern

对于使用协调器模式的应用

Trigger coordinator methods from debug URL handler:
swift
coordinator.navigate(to: .fromDebugURL(url))
从调试URL处理器中触发协调器方法:
swift
coordinator.navigate(to: .fromDebugURL(url))

For Apps Using Custom Routing

对于使用自定义路由的应用

Integrate with your router's navigation API:
swift
AppRouter.shared.push(Screen.fromDebugURL(url))
Key principle: Debug deep links should USE existing navigation, not replace it.

与路由器的导航API集成:
swift
AppRouter.shared.push(Screen.fromDebugURL(url))
核心原则:调试深度链接应该使用现有导航系统,而不是替换它。

Advanced Patterns

高级模式

Pattern 5: Parameterized State Setup

模式5:参数化状态设置

swift
#if DEBUG
case "test-scenario":
    // Parse complex test scenario from URL
    // Example: debug://test-scenario?user=premium&recipes=empty&network=slow

    if let userType = url.queryItems?["user"] {
        configureUser(type: userType) // "premium", "free", "trial"
    }

    if let recipesState = url.queryItems?["recipes"] {
        configureRecipes(state: recipesState) // "empty", "full", "error"
    }

    if let networkState = url.queryItems?["network"] {
        configureNetwork(state: networkState) // "fast", "slow", "offline"
    }

    // Now navigate
    path.append(Destination.recipes)
#endif
Usage:
bash
undefined
swift
#if DEBUG
case "test-scenario":
    // 从URL中解析复杂的测试场景
    // 示例: debug://test-scenario?user=premium&recipes=empty&network=slow

    if let userType = url.queryItems?["user"] {
        configureUser(type: userType) // "premium", "free", "trial"
    }

    if let recipesState = url.queryItems?["recipes"] {
        configureRecipes(state: recipesState) // "empty", "full", "error"
    }

    if let networkState = url.queryItems?["network"] {
        configureNetwork(state: networkState) // "fast", "slow", "offline"
    }

    // 跳转到目标页面
    path.append(Destination.recipes)
#endif
使用方式:
bash
undefined

Test premium user with empty recipe list

测试高级用户的空菜谱列表场景

xcrun simctl openurl booted "debug://test-scenario?user=premium&recipes=empty"
xcrun simctl openurl booted "debug://test-scenario?user=premium&recipes=empty"

Test slow network with error handling

测试慢网络下的错误处理场景

xcrun simctl openurl booted "debug://test-scenario?network=slow&recipes=error"

---
xcrun simctl openurl booted "debug://test-scenario?network=slow&recipes=error"

---

Pattern 6: Screenshot Automation Helper

模式6:截图自动化辅助工具

Create a single URL that sets up AND captures state:
swift
#if DEBUG
case "screenshot":
    // Parse screen and configuration
    guard let screen = url.queryItems?["screen"] else { return }

    // Configure state
    if let state = url.queryItems?["state"] {
        applyState(state)
    }

    // Navigate
    navigate(to: screen)

    // Post notification for external capture
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        NotificationCenter.default.post(
            name: .readyForScreenshot,
            object: screen
        )
    }
#endif
Usage:
bash
undefined
创建一个可同时设置状态并触发截图的URL:
swift
#if DEBUG
case "screenshot":
    // 解析目标页面和配置
    guard let screen = url.queryItems?["screen"] else { return }

    // 配置状态
    if let state = url.queryItems?["state"] {
        applyState(state)
    }

    // 跳转到目标页面
    navigate(to: screen)

    // 发送通知以触发外部截图
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        NotificationCenter.default.post(
            name: .readyForScreenshot,
            object: screen
        )
    }
#endif
使用方式:
bash
undefined

Navigate to login screen with error state, wait, then screenshot

跳转到带错误状态的登录页面,等待后截图

xcrun simctl openurl booted "debug://screenshot?screen=login&state=error" sleep 2 xcrun simctl io booted screenshot login-error.png

---
xcrun simctl openurl booted "debug://screenshot?screen=login&state=error" sleep 2 xcrun simctl io booted screenshot login-error.png

---

Related Skills

相关技能

  • axiom-swiftui-nav
    — Production deep linking and NavigationStack patterns
  • simulator-tester
    — Automated simulator testing using debug deep links
  • axiom-xcode-debugging
    — Environment-first debugging workflows

  • axiom-swiftui-nav
    — 生产环境深度链接和NavigationStack模式
  • simulator-tester
    — 使用调试深度链接进行自动化模拟器测试
  • axiom-xcode-debugging
    — 基于环境的优先调试流程

Summary

总结

Debug deep links enable:
  • Closed-loop debugging with visual verification
  • 60-75% faster iteration on visual fixes
  • Automated testing without manual navigation
  • Screenshot automation for any app state
Remember:
  1. Wrap ALL debug code in
    #if DEBUG
  2. Strip URL scheme from release builds
  3. Integrate with existing navigation, don't duplicate
  4. Validate all parameters (no force unwraps)
  5. Document for team members
调试深度链接可实现:
  • 带视觉验证的闭环调试
  • 视觉修复的迭代速度提升60-75%
  • 无需手动导航的自动化测试
  • 任意应用状态下的截图自动化
请记住:
  1. 所有调试代码都要用
    #if DEBUG
    包裹
  2. 从发布构建中移除URL Scheme
  3. 与现有导航系统集成,不要重复逻辑
  4. 验证所有参数(不使用强制解包)
  5. 为团队成员文档化相关内容