skip-dev

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Skip Multiplatform Development

Skip 多平台开发

Overview

概述

Skip (https://skip.dev) enables building native iOS and Android apps from a single Swift/SwiftUI codebase. It works as an Xcode plugin that continuously generates an equivalent Android project using Jetpack Compose. iOS runs SwiftUI directly; Android uses Skip-generated Kotlin/Compose code.
Skip(https://skip.dev)支持通过单一 Swift/SwiftUI 代码库构建原生 iOS 和 Android 应用。它作为 Xcode 插件运行,可持续生成使用 Jetpack Compose 的等效 Android 项目。iOS 直接运行 SwiftUI;Android 使用 Skip 生成的 Kotlin/Compose 代码。

Decision Tree: Skip Mode Selection

决策树:Skip 模式选择

Before writing code, determine the correct Skip mode:
Is this a NEW project?
├── YES → Does it need C/C++ code or complex Swift features?
│   ├── YES → Use Skip Fuse (native)
│   └── NO → Does app size matter (Fuse adds ~60MB)?
│       ├── YES → Use Skip Lite (transpiled)
│       └── NO → Use Skip Fuse (native) — preferred default
└── NO → Check skip.yml for `mode:` setting
    ├── mode: 'native' → Skip Fuse
    └── mode: 'transpiled' → Skip Lite
编写代码前,请确定正确的 Skip 模式:
Is this a NEW project?
├── YES → Does it need C/C++ code or complex Swift features?
│   ├── YES → Use Skip Fuse (native)
│   └── NO → Does app size matter (Fuse adds ~60MB)?
│       ├── YES → Use Skip Lite (transpiled)
│       └── NO → Use Skip Fuse (native) — preferred default
└── NO → Check skip.yml for `mode:` setting
    ├── mode: 'native' → Skip Fuse
    └── mode: 'transpiled' → Skip Lite

Skip Fuse (Native Mode)

Skip Fuse(原生模式)

  • Compiles Swift natively for Android using the Swift SDK for Android
  • Full Swift language support, faithful runtime, complete stdlib/Foundation
  • Can integrate C/C++ libraries
  • Trade-off: +60MB app size, requires bridging for Kotlin interop, slower builds
  • 使用 Android Swift SDK 为 Android 原生编译 Swift
  • 完整支持 Swift 语言、忠实的运行时环境、完整的标准库/Foundation
  • 可集成 C/C++ 库
  • 权衡点:应用体积增加约60MB,Kotlin 互操作需要桥接,构建速度较慢

Skip Lite (Transpiled Mode)

Skip Lite(转译模式)

  • Converts Swift source code → Kotlin source code
  • Direct access to Kotlin/Java APIs from
    #if SKIP
    blocks
  • Smaller app size, faster builds, more transparent output
  • Trade-off: limited Swift language features, limited stdlib support
  • 将 Swift 源代码转换为 Kotlin 源代码
  • 可从
    #if SKIP
    代码块直接访问 Kotlin/Java API
  • 应用体积更小、构建速度更快、输出更透明
  • 权衡点:Swift 语言特性支持有限,标准库支持有限

Configuration in skip.yml

skip.yml 配置

yaml
undefined
yaml
undefined

For Fuse (native) mode:

For Fuse (native) mode:

mode: 'native' bridging: true
mode: 'native' bridging: true

For Lite (transpiled) mode:

For Lite (transpiled) mode:

mode: 'transpiled'
undefined
mode: 'transpiled'
undefined

Project Structure

项目结构

App Projects

应用项目

MyApp/
├── Package.swift              # SPM dependencies & targets
├── Skip.env                   # Skip environment config
├── Sources/
│   ├── MyApp/                 # Main app module (SwiftUI views)
│   │   ├── MyApp.swift        # App entry point (@main)
│   │   ├── ContentView.swift
│   │   └── Skip/              # Android-specific Kotlin files
│   │       └── skip.yml       # Skip module configuration
│   └── MyAppModel/            # Shared model module
│       ├── DataModel.swift
│       └── Skip/
│           └── skip.yml
├── Tests/
│   ├── MyAppTests/
│   └── MyAppModelTests/
├── Darwin/                    # iOS-specific
│   ├── MyApp.xcodeproj
│   ├── MyApp.xcconfig
│   ├── Assets.xcassets/
│   └── Info.plist
└── Android/                   # Android-specific
    ├── settings.gradle.kts
    └── app/
        ├── build.gradle.kts
        ├── src/main/AndroidManifest.xml
        └── src/main/kotlin/.../Main.kt
MyApp/
├── Package.swift              # SPM dependencies & targets
├── Skip.env                   # Skip environment config
├── Sources/
│   ├── MyApp/                 # Main app module (SwiftUI views)
│   │   ├── MyApp.swift        # App entry point (@main)
│   │   ├── ContentView.swift
│   │   └── Skip/              # Android-specific Kotlin files
│   │       └── skip.yml       # Skip module configuration
│   └── MyAppModel/            # Shared model module
│       ├── DataModel.swift
│       └── Skip/
│           └── skip.yml
├── Tests/
│   ├── MyAppTests/
│   └── MyAppModelTests/
├── Darwin/                    # iOS-specific
│   ├── MyApp.xcodeproj
│   ├── MyApp.xcconfig
│   ├── Assets.xcassets/
│   └── Info.plist
└── Android/                   # Android-specific
    ├── settings.gradle.kts
    └── app/
        ├── build.gradle.kts
        ├── src/main/AndroidManifest.xml
        └── src/main/kotlin/.../Main.kt

Framework Projects (SPM Packages)

框架项目(SPM 包)

MyFramework/
├── Package.swift
├── Sources/
│   └── MyFramework/
│       ├── MyFramework.swift
│       └── Skip/
│           └── skip.yml
└── Tests/
    └── MyFrameworkTests/
        └── MyFrameworkTests.swift
Key point: Frameworks do NOT have Darwin/ or Android/ folders. The Android build is triggered by running unit tests, not by building an app.
MyFramework/
├── Package.swift
├── Sources/
│   └── MyFramework/
│       ├── MyFramework.swift
│       └── Skip/
│           └── skip.yml
└── Tests/
    └── MyFrameworkTests/
        └── MyFrameworkTests.swift
关键点:框架项目没有 Darwin/ 或 Android/ 文件夹。Android 构建是通过运行单元测试触发的,而非构建应用。

Building

构建

Apps: Build from Xcode

应用:从 Xcode 构建

  1. Open the
    .xcodeproj
    in
    Darwin/
  2. Select an iOS Simulator destination
  3. Build & Run — the Skip plugin automatically generates and builds the Android project
  4. Android output appears in the
    SkipStone/plugins
    group in the Xcode project navigator
Android build behavior is controlled in
.xcconfig
:
SKIP_ACTION = launch   # Build and launch Android emulator (default)
SKIP_ACTION = build    # Build Android only, don't launch
SKIP_ACTION = none     # Skip Android build entirely
  1. 打开
    Darwin/
    目录下的
    .xcodeproj
  2. 选择 iOS 模拟器作为目标设备
  3. 构建并运行 — Skip 插件会自动生成并构建 Android 项目
  4. Android 输出将显示在 Xcode 项目导航器的
    SkipStone/plugins
    组中
Android 构建行为
.xcconfig
控制:
SKIP_ACTION = launch   # Build and launch Android emulator (default)
SKIP_ACTION = build    # Build Android only, don't launch
SKIP_ACTION = none     # Skip Android build entirely

Apps: Build from CLI

应用:从 CLI 构建

bash
undefined
bash
undefined

Build iOS project

Build iOS project

xcodebuild -project Darwin/MyApp.xcodeproj -scheme MyApp
-destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=latest' build
xcodebuild -project Darwin/MyApp.xcodeproj -scheme MyApp
-destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=latest' build

Export Android APK

Export Android APK

skip export --project Darwin/MyApp.xcodeproj --appid com.example.myapp
undefined
skip export --project Darwin/MyApp.xcodeproj --appid com.example.myapp
undefined

Frameworks: Trigger Android Build via Tests

框架:通过测试触发 Android 构建

bash
undefined
bash
undefined

Run against macOS destination to trigger Android build

Run against macOS destination to trigger Android build

swift test
swift test

OR

OR

skip test

**Critical:** You MUST run framework tests against a **macOS** destination to perform an Android build. Testing against an iOS destination will NOT run Android tests.
skip test

**重要提示**:必须针对 **macOS** 目标运行框架测试才能执行 Android 构建。针对 iOS 目标测试不会运行 Android 测试。

Debugging

调试

iOS Debugging

iOS 调试

  • Standard Xcode debugging: breakpoints, LLDB, view hierarchy inspector
  • Use
    OSLog.Logger
    for logging (NOT
    print()
    — print doesn't work on Android)
swift
import OSLog

let logger = Logger(subsystem: "com.example.myapp", category: "networking")
logger.info("Request started: \(url)")
logger.error("Request failed: \(error.localizedDescription)")
  • 标准 Xcode 调试:断点、LLDB、视图层次结构检查器
  • 使用
    OSLog.Logger
    进行日志记录(不要使用
    print()
    — print 在 Android 上无法工作)
swift
import OSLog

let logger = Logger(subsystem: "com.example.myapp", category: "networking")
logger.info("Request started: \(url)")
logger.error("Request failed: \(error.localizedDescription)")

Android Debugging

Android 调试

  1. Logcat — primary Android debugging tool:
bash
undefined
  1. Logcat — 主要的 Android 调试工具:
bash
undefined

Filter logs by app tag

Filter logs by app tag

adb logcat -s MyApp
adb logcat -s MyApp

Filter by Skip logger output

Filter by Skip logger output

adb logcat | grep "com.example.myapp"

2. **Android Studio** — open the generated Gradle project:
   - For apps: find generated source under `SkipStone/plugins` in Xcode navigator → right-click → "Open in Android Studio"
   - For frameworks: open the `SkipLink/` folder in Android Studio

3. **View generated Kotlin code** — invaluable for debugging transpilation issues:
   - In Xcode, expand `SkipStone/plugins` (apps) or `SkipLink` (frameworks)
    - Find the `.kt` files corresponding to your Swift source
    - Use Kotlin compiler line numbers to locate the failing generated statement, then map it back to the matching Swift declaration
    - Apply fixes in Swift source (or Skip Comments), then rebuild; do not edit generated `.kt` files directly (they are overwritten)

4. **Crash traces** — demangle Swift symbols:
```bash
xcrun swift-demangle <mangled_symbol>
adb logcat | grep "com.example.myapp"

2. **Android Studio** — 打开生成的 Gradle 项目:
   - 对于应用:在 Xcode 导航器中找到 `SkipStone/plugins` 下的生成源码 → 右键 → "在 Android Studio 中打开"
   - 对于框架:在 Android Studio 中打开 `SkipLink/` 文件夹

3. **查看生成的 Kotlin 代码** — 对调试转译问题非常重要:
   - 在 Xcode 中展开 `SkipStone/plugins`(应用)或 `SkipLink`(框架)
   - 找到与 Swift 源码对应的 `.kt` 文件
   - 使用 Kotlin 编译器行号定位失败的生成语句,然后映射回对应的 Swift 声明
   - 在 Swift 源码(或 Skip 注释)中应用修复,然后重新构建;不要直接编辑生成的 `.kt` 文件(它们会被覆盖)

4. **崩溃追踪** — 还原 Swift 符号:
```bash
xcrun swift-demangle <mangled_symbol>

Common Build Errors

常见构建错误

ErrorCauseFix
No such module 'Skip...'
Skip plugin not installedRun
skip checkup
Cannot find type...in scope
Unsupported Swift API on AndroidUse
#if !os(Android)
guard or find Skip equivalent
Gradle sync failureAndroid SDK issueRun
skip doctor
then
skip android sdk install
Bridging error
Missing bridge annotationAdd
// SKIP @bridge
or enable
bridging: true
in skip.yml
SkipNotSupportedError
Using unsupported SkipUI featureCheck SkipUI docs; provide Android-specific alternative
错误原因修复方案
No such module 'Skip...'
Skip 插件未安装运行
skip checkup
Cannot find type...in scope
Android 不支持该 Swift API使用
#if !os(Android)
保护或寻找 Skip 等效方案
Gradle 同步失败Android SDK 问题运行
skip doctor
然后执行
skip android sdk install
Bridging error
缺少桥接注解添加
// SKIP @bridge
或在 skip.yml 中启用
bridging: true
SkipNotSupportedError
使用了不支持的 SkipUI 特性查看 SkipUI 文档;提供 Android 特定的替代方案

Transpilation Error Workflow (Using Generated Kotlin)

转译错误处理流程(使用生成的 Kotlin 代码)

When Lite mode transpilation fails, use this quick loop:
  1. Trigger a build (
    xcodebuild
    , Xcode Run, or
    skip test
    ) and capture the first Kotlin error.
  2. Open the generated Kotlin file and line from the compiler output (
    SkipStone/plugins
    for apps,
    SkipLink
    for frameworks).
  3. Identify the original Swift declaration that produced that Kotlin block.
  4. Fix the Swift source using one of:
    • simpler type annotations (especially around generics/optionals)
    • platform guards (
      #if os(Android)
      /
      #if !os(Android)
      /
      #if SKIP
      )
    • Skip Comments (
      SKIP INSERT
      ,
      SKIP REPLACE
      ,
      SKIP DECLARE
      ,
      SKIP NOWARN
      )
  5. Rebuild and verify the same Kotlin section now compiles.
Rule of thumb: treat generated Kotlin as a diagnostic artifact, not a source of truth. Keep permanent fixes in Swift and
Skip/
support files.
当 Lite 模式转译失败时,使用以下快速流程:
  1. 触发构建(
    xcodebuild
    、Xcode 运行或
    skip test
    )并捕获第一个 Kotlin 错误。
  2. 打开编译器输出中指定的生成 Kotlin 文件和行(应用为
    SkipStone/plugins
    ,框架为
    SkipLink
    )。
  3. 识别生成该 Kotlin 代码块的原始 Swift 声明。
  4. 使用以下方式修复 Swift 源码:
    • 更简单的类型注解(尤其是泛型/可选类型)
    • 平台保护(
      #if os(Android)
      /
      #if !os(Android)
      /
      #if SKIP
    • Skip 注释(
      SKIP INSERT
      SKIP REPLACE
      SKIP DECLARE
      SKIP NOWARN
  5. 重新构建并验证同一 Kotlin 部分现在可以编译。
经验法则:将生成的 Kotlin 代码视为诊断工件,而非事实来源。永久修复应保留在 Swift 和
Skip/
支持文件中。

Testing

测试

Running Tests

运行测试

bash
undefined
bash
undefined

Swift tests only (iOS)

Swift tests only (iOS)

swift test
swift test

Cross-platform parity tests (iOS + Android via Robolectric)

Cross-platform parity tests (iOS + Android via Robolectric)

skip test
skip test

Android emulator tests

Android emulator tests

ANDROID_SERIAL=emulator-5554 skip test
undefined
ANDROID_SERIAL=emulator-5554 skip test
undefined

Writing Cross-Platform Tests

编写跨平台测试

swift
import XCTest

final class MyTests: XCTestCase {
    func testSharedLogic() {
        // Runs on both platforms
        XCTAssertEqual(calculate(2, 3), 5)
    }

    #if !os(Android)
    func testIOSOnly() {
        // iOS-specific test
    }
    #endif

    #if os(Android) || ROBOLECTRIC
    func testAndroidOnly() {
        // Android-specific test (runs on Robolectric too)
    }
    #endif
}
swift
import XCTest

final class MyTests: XCTestCase {
    func testSharedLogic() {
        // Runs on both platforms
        XCTAssertEqual(calculate(2, 3), 5)
    }

    #if !os(Android)
    func testIOSOnly() {
        // iOS-specific test
    }
    #endif

    #if os(Android) || ROBOLECTRIC
    func testAndroidOnly() {
        // Android-specific test (runs on Robolectric too)
    }
    #endif
}

Robolectric Testing

Robolectric 测试

Skip uses Robolectric for fast, Mac-based Android testing without an emulator. Use
#if os(Android) || ROBOLECTRIC
to include tests that should run on both Android emulator and Robolectric.
Skip 使用 Robolectric 进行快速的基于 Mac 的 Android 测试,无需模拟器。使用
#if os(Android) || ROBOLECTRIC
包含应在 Android 模拟器和 Robolectric 上都运行的测试。

Conditional Compilation

条件编译

Platform Directives

平台指令

swift
#if os(Android)
    // Android-only code
#else
    // iOS-only code
#endif

#if !os(Android)
    // iOS-only code
#endif

#if SKIP
    // Only in transpiled Kotlin code (Skip Lite)
    // Can call Kotlin/Java APIs directly here
#endif

#if !SKIP
    // Only in native Swift (iOS, or Fuse Android)
#endif

#if ROBOLECTRIC
    // Only during Robolectric test execution
#endif
swift
#if os(Android)
    // Android-only code
#else
    // iOS-only code
#endif

#if !os(Android)
    // iOS-only code
#endif

#if SKIP
    // Only in transpiled Kotlin code (Skip Lite)
    // Can call Kotlin/Java APIs directly here
#endif

#if !SKIP
    // Only in native Swift (iOS, or Fuse Android)
#endif

#if ROBOLECTRIC
    // Only during Robolectric test execution
#endif

Skip Comments

Skip 注释

Skip Comments control how Swift code is transpiled to Kotlin:
swift
// SKIP INSERT: val androidSpecificVal = "only in Kotlin output"

// SKIP REPLACE: fun customKotlinImplementation() { ... }
func swiftImplementation() { ... }

// SKIP DECLARE: annotation class MyAnnotation
// SKIP DECLARE: typealias PlatformType = android.content.Context

// SKIP NOWARN
let _ = someUnsupportedPattern  // Suppresses transpilation warning

// SKIP @bridge
public func bridgedFunction() { }  // Exposes to Kotlin in Fuse mode

// SKIP @nobridge
public func noBridge() { }  // Prevents bridging

// SKIP @nocopy
struct LargeData { }  // Skip copy semantics for structs

// SKIP SYMBOLFILE
// Generates .skipmodule symbol file for the module
Skip 注释控制 Swift 代码如何转译为 Kotlin:
swift
// SKIP INSERT: val androidSpecificVal = "only in Kotlin output"

// SKIP REPLACE: fun customKotlinImplementation() { ... }
func swiftImplementation() { ... }

// SKIP DECLARE: annotation class MyAnnotation
// SKIP DECLARE: typealias PlatformType = android.content.Context

// SKIP NOWARN
let _ = someUnsupportedPattern  // Suppresses transpilation warning

// SKIP @bridge
public func bridgedFunction() { }  // Exposes to Kotlin in Fuse mode

// SKIP @nobridge
public func noBridge() { }  // Prevents bridging

// SKIP @nocopy
struct LargeData { }  // Skip copy semantics for structs

// SKIP SYMBOLFILE
// Generates .skipmodule symbol file for the module

Skip CLI Quick Reference

Skip CLI 速查参考

bash
skip create          # Interactive project creation wizard
skip init            # Non-interactive project init
skip test            # Run cross-platform tests
skip export          # Export Android APK/AAB
skip checkup         # Verify Skip installation
skip doctor          # Diagnose and fix issues
skip upgrade         # Update Skip to latest version
skip verify          # Verify project configuration
bash
skip create          # Interactive project creation wizard
skip init            # Non-interactive project init
skip test            # Run cross-platform tests
skip export          # Export Android APK/AAB
skip checkup         # Verify Skip installation
skip doctor          # Diagnose and fix issues
skip upgrade         # Update Skip to latest version
skip verify          # Verify project configuration

Android-specific

Android-specific

skip android build # Build Android project skip android test # Run Android tests skip android emulator create # Create AVD emulator skip android emulator launch # Launch emulator skip android sdk install # Install Android SDK components skip android sdk list # List available SDK packages
undefined
skip android build # Build Android project skip android test # Run Android tests skip android emulator create # Create AVD emulator skip android emulator launch # Launch emulator skip android sdk install # Install Android SDK components skip android sdk list # List available SDK packages
undefined

References

参考文献

For detailed reference material, load from the
references/
directory:
  • references/transpilation.md
    — Swift language features support table, builtin types, generics, structs, concurrency, numeric types, plus a Kotlin-output troubleshooting workflow for transpilation failures
  • references/skip-ui.md
    — Supported SwiftUI components, ComposeView integration, composeModifier, Material3 customization, animation, images, navigation, lists, gestures
  • references/cross-platform.md
    — Calling Kotlin/Java APIs, Compose integration, AnyDynamicObject, Kotlin files in Sources, Android Studio workflow, model integration patterns
  • references/bridging.md
    — skip.yml configuration, @bridge/@bridgeMembers/@nobridge annotations, bridging Swift↔Kotlin, kotlincompat option, AnyDynamicObject usage
  • references/dependencies.md
    — Adding Skip/SwiftPM/Java/Kotlin dependencies, platform-conditional dependencies, skip.yml build blocks
  • references/cli.md
    — Full Skip CLI command reference with options, examples, and common workflows
  • references/unit-testing.md
    — How unit testing works in Skip, execution model (
    swift test
    vs
    skip test
    ), cross-platform test patterns, Robolectric usage, and CI strategy
Load a reference with:
read_file('<base_dir>/references/<filename>')
如需详细参考资料,请从
references/
目录加载:
  • references/transpilation.md
    — Swift 语言特性支持表、内置类型、泛型、结构体、并发、数值类型,以及针对转译失败的 Kotlin 输出故障排除流程
  • references/skip-ui.md
    — 支持的 SwiftUI 组件、ComposeView 集成、composeModifier、Material3 自定义、动画、图片、导航、列表、手势
  • references/cross-platform.md
    — 调用 Kotlin/Java API、Compose 集成、AnyDynamicObject、Sources 中的 Kotlin 文件、Android Studio 工作流、模型集成模式
  • references/bridging.md
    — skip.yml 配置、@bridge/@bridgeMembers/@nobridge 注解、Swift↔Kotlin 桥接、kotlincompat 选项、AnyDynamicObject 使用
  • references/dependencies.md
    — 添加 Skip/SwiftPM/Java/Kotlin 依赖、平台条件依赖、skip.yml 构建块
  • references/cli.md
    — 完整的 Skip CLI 命令参考,包含选项、示例和常见工作流
  • references/unit-testing.md
    — Skip 中的单元测试工作原理、执行模型(
    swift test
    vs
    skip test
    )、跨平台测试模式、Robolectric 使用和 CI 策略
加载参考资料的命令:
read_file('<base_dir>/references/<filename>')