Skip
Skip 是一种使用 Swift 创建双平台移动应用的技术。阅读这篇介绍以了解更多关于 Skip 的信息。
这个仓库托管了 Skip 开发工具链,也称为 SkipStone。它还托管了 Skip 论坛,用于一般讨论以及特定的问题和错误报告。
入门
系统要求
Skip 需要一台安装了 Xcode 15、Android Studio 2023 和 Homebrew 的 macOS 13 开发机器。
安装
通过运行以下终端命令安装 Skip:
brew install skiptools/skip/skip
这将下载并安装 skip
工具本身,以及构建和测试应用程序 Kotlin/Android 端所需的 gradle
和 JDK 依赖项。注意:如果你的机器上还没有安装兼容的 JDK+,你可能需要输入管理员密码来完成安装。
通过运行以下命令确保满足开发先决条件:
skip checkup
如果检查通过,你就可以开始使用 Skip 进行开发了!
创建应用 {#app_development}
使用以下命令创建新的应用项目:
skip init --open-xcode --appid=bundle.id project-name AppName
例如:
skip init --open-xcode --appid=com.xyz.HelloSkip hello-skip HelloSkip
这将创建一个 hello-skip/
文件夹,其中包含一个新的 SwiftPM 包,包含一个名为 HelloSkip
的单一模块,以及名为 Darwin
和 Android
的文件夹和共享的 Skip.env
应用配置文件。Darwin
文件夹将包含一个带有 HelloSkip
目标的 HelloSkip.xcodeproj
项目,可以在 Xcode 中打开。
Xcode 将打开新项目,但在你可以构建和启动转译后的应用之前,需要运行一个 Android 模拟器。启动 Android Studio.app
并从欢迎对话框的省略号菜单中打开 Virtual Device Manager
。从那里,Create Device
(例如,"Pixel 6"),然后 Launch
模拟器。
一旦 Android 模拟器运行,在 Xcode 中选择并运行 HelloSkip
目标。第一次构建将花费一些时间来编译 Skip 库,你可能会看到一个对话框,确认你信任 Skip 插件。一旦构建和运行操作完成,SwiftUI 应用将在选定的 iOS 模拟器中打开,同时转译后的应用将在当前运行的 Android 模拟器中启动。
浏览到 ContentView.swift
文件,做一些小的修改并重新运行目标:应用将在两个平台上同时重新构建和重新运行,包含你的更改。
查看产品文档以获取有关使用 Skip 开发的更多信息。祝你使用 Skip 愉快!
创建多模块应用
Skip 设计用于适应和鼓励使用多模块项目。默认的 skip init
命令为简单起见创建单模块应用,但你可以通过在命令末尾指定额外的模块名称来创建模块化项目。例如:
skip init --open-xcode --appid=com.xyz.HelloSkip multi-project HelloSkip HelloModel HelloCore
这个命令将创建一个包含三个模块的 SwiftPM 项目:HelloSkip
、HelloModel
和 HelloCore
。这种模块创建的规则是,所有模块都依赖于其后续的对等模块,第一个模块(HelloSkip
)最初依赖于 SkipUI
,第二个模块依赖于 SkipModel
,链中的最后一个模块依赖于 SkipFoundation
。可以手动编辑 Package.swift
文件来重新安排依赖关系,或添加对外部 Skip 框架的新依赖,如新兴的 SkipSQL 或 SkipXML 库。
创建双平台框架 {#framework_development}
Skip 框架项目是封装通用功能的纯 SwiftPM 包。它们比应用项目更简单,因为它们不需要 Darwin/
和 Android/
文件夹。
每个核心 Skip 兼容性框架(skip-lib、skip-unit、skip-foundation 和 skip-ui)都是 Skip 框架项目。其他常用项目包括 skip-sql、skip-script 和 skip-zip。
可以使用以下命令创建并打开新的框架项目:
skip init --build --test lib-name ModuleName
这将创建一个新的 lib-name
文件夹,其中包含一个带有 ModuleName
和 ModuleNameTests
目标的 Package.swift
。
可以在 Xcode.app 中打开这个项目,你可以用它来构建和运行单元测试。从终端运行 swift build
和 swift test
也可以用于作为持续集成过程的一部分进行无头测试。
Skip 框架结构
Skip 框架的结构与任何其他 SPM 包完全相同:
lib-name
├── Package.resolved
├── Package.swift
├── README.md
├── Sources
│ └── ModuleName
│ ├── ModuleName.swift
│ ├── Resources
│ │ └── Localizable.xcstrings
│ └── Skip
│ └── skip.yml
└── Tests
└── ModuleNameTests
├── ModuleNameTests.swift
├── Resources
│ └── TestData.json
├── Skip
│ └── skip.yml
└── XCSkipTests.swift
Skip 框架使用标准的 Package.swift
文件,但增加了对 skip
的依赖和使用 skipstone
插件进行转译:
// swift-tools-version: 5.8
import PackageDescription
let package = Package(
name: "lib-name",
defaultLocalization: "en",
platforms: [.iOS(.v16), .macOS(.v13), .tvOS(.v16), .watchOS(.v9), .macCatalyst(.v16)],
products: [
.library(name: "ModuleName", targets: ["ModuleName"]),
],
dependencies: [
.package(url: "https://source.skip.tools/skip.git", from: "1.0.4"),
.package(url: "https://source.skip.tools/skip-foundation.git", from: "0.0.0"),
],
targets: [
.target(name: "ModuleName", plugins: [.plugin(name: "skipstone", package: "skip")]),
.testTarget(name: "ModuleNameTests", dependencies: ["ModuleName"], plugins: [.plugin(name: "skipstone", package: "skip")]),
]
)
skip init
参考
zap /tmp % skip init --help
概述: 初始化一个新的Skip项目
用法: skip init [<选项>] <项目名称> <模块名称> ...
参数:
<项目名称> 项目文件夹名称
<模块名称> 要创建的模块名称
输出选项:
-o, --output <路径> 将输出发送到指定文件(stdout: -)
-E, --message-errout 将消息输出到输出而不是stderr
-v, --verbose 是否显示详细消息
-q, --quiet 安静模式:禁止输出
-J, --json 以格式化JSON输出
-j, --json-compact 以紧凑JSON输出
-M, --message-plain 以纯文本而非JSON显示控制台消息
-A, --json-array 将JSON输出包装并分隔为数组
--plain/--no-plain 不显示颜色或进度动画(默认:--no-plain)
创建选项:
--id <id> 应用程序标识符(默认:net.example.MyApp)
-d, --dir <目录> 项目创建的基础文件夹
-c, --configuration <c> 配置调试/发布(默认:调试)
-t, --template <id> 新项目的模板名称/ID(默认:skipapp)
-h, --template-host <主机>
模板仓库的主机名(默认:https://github.com)
-f, --template-file <zip>
要使用的模板zip文件路径
--resource-path <资源路径>
资源文件夹名称(默认:Resources)
--chain/--no-chain 在模块间创建库依赖(默认:--chain)
--zero/--no-zero 在Package.swift中添加SKIP_ZERO环境检查(默认:--zero)
--git-repo/--no-git-repo
为应用创建本地git仓库(默认:--no-git-repo)
--free 以免费模式创建包
--show-tree/--no-show-tree
显示新文件的文件系统树摘要(默认:--no-show-tree)
--module-tests/--no-module-tests
是否创建测试模块(默认:--module-tests)
--validate-package/--no-validate-package
验证生成的Package.swift文件(默认:--validate-package)
工具选项:
--xcodebuild <路径> Xcode命令路径
--swift <路径> Swift命令路径
--gradle <路径> Gradle命令路径
--adb <路径> ADB命令路径
--emulator <路径> Android模拟器路径
--android-home <路径> Android SDK路径(ANDROID_HOME)
构建选项:
--build/--no-build 运行项目构建(默认:--build)
--test/--no-test 运行项目测试(默认:--no-test)
--verify/--no-verify 验证项目输出(默认:--verify)
选项:
--appid <appid> 将库嵌入具有给定包ID的应用
--icon-color <RGB> 图标背景的RGB十六进制颜色(默认:4994EC)
--version <版本> 将初始版本设置为给定值
--open-xcode 打开生成的Xcode项目
--open-gradle 打开生成的Gradle项目
-h, --help 显示帮助信息。
故障排除
Skip的架构依赖于Xcode 15和Swift Package Manager 5.9使用的插件系统的最新进展。当出现意外问题时,通常最好的第一步是清理Xcode构建("产品"→"清理构建文件夹")并重置包("文件"→"包"→"重置包缓存")。有时需要重启Xcode,甚至可能需要删除本地的"DerivedData/"文件夹。
下面列出了具体的已知错误情况。请搜索文档、问题和讨论以获取更多信息并报告问题。
-
Xcode有时会报告如下错误消息:
Internal inconsistency error (didStartTask): targetID (174) not found in _activeTargets. Internal inconsistency error (didEndTask): '12' missing from _activeTasks.
当这些错误发生时,构建似乎成功完成,但更改未被应用。不幸的是,这是Xcode的一个错误。我们发现以下解决方法:
- 继续重试构建。最终Xcode可能会成功完成,尽管错误通常会变得越来越频繁,直到你被迫采用下面的其他解决方案。
- 构建不同的目标然后重新构建你的应用目标可能会清除错误。
- 重启Xcode。
- 清理并重新构建。
你可以在Swift.org论坛上阅读更多关于这个Xcode错误的信息。
-
Skip可能会在构建错误中高亮显示错误的行。当Skip显示错误的行号时,通常只偏差一行。