最近在找资料的时候,机缘巧合发现了一个有趣的商业跨平台框架 Skip ,刚好看到了它发布 1.0 正式版,主要作用是将 Swift 开发引入到 Android 领域,这样 App 就可以共享 Swift 的业务逻辑,在 SwiftUI 中完成 Android App,用 Skip 的话说就是:
“Skip brings Swift app development to Android. Share Swift business logic, or write entire cross-platform apps in SwiftUI.”
至于为什么说是原生级?稍微了解之后,我发现它的理念和思路有点意思,或者说类似的路子国内也有,例如曾经写过的 《uni-app-x 了解过吗?》 ,从思路上看它们都是走的「转译」的路线,当然这个路线成本不低,比如在 uni-app-x 文章的评论区,就有大哥有比较深的感悟:
当然,Skip 和 uni-app-x 比较大的区别在于:它是直接通过 Swift / SwiftUI 去转移为 Kotlin / Compose,所以在语法和兼容成本会更低一点点,因为它只需要实现 Android 平台的转移,iOS 平台本身就是 Native 。
另外,Skip 的可脱离性质才是我觉得最有意思的,这个我们后续会讲到。
至于为什么会想到用 Swift 来做跨平台?因为在 Skip 的产品理念里,移动应用基本是 iOS 先行,而后才考虑 Android,所以用 Swift 做跨平台是它们的最佳实践:
“In our experience, however, apps are generally made for iOS first. Clients ask for an iOS app, then expect a port to the Play Store. Large tech companies design for iOS first, then adapt their designs for Android.”
当然,作为商业框架, Skip 的目标其实就是在 Xcode 中用 Swift / SwiftUI 写完代码后,可以通过 Xcode 插件自动处理生产 Android 版本。
当然理想和现实还是有一些区别,毕竟语法特效和平台 API 差异注定在「转译」时需要做阉割。
回到 Skip 的实现,在 Skip Engine 内部,它底层采用的是原生平台的框架实现:iOS 上 Swift / SwiftUI,Android 上 Kotlin / Compose,也就是纯纯原生,没有桥接和第三方运行时,事实上 Skip 在 iOS 上会直接调用 Swift 或 Objective C API,在 Android 上直接调用 Kotlin 或 Java API ,所以其实它在 Android 上等于是一个「转译」框架。
所以从运行上看,他们都是原生级别的 App ,因为跨平台能力是在编译期处理完成,这点和 uni-app-x 一样。
Skip 的核心是它的 Swift to Kotlin 转译器,转译器使用了 Apple 的 SwiftSyntax 来解析 Swift 源码,然后将代码转换为可读的 Kotlin ,甚至连注释也会一同转换,而类似 SwiftUI 和 Compose 都是响应式的 UI 开发模式,所以从「转译」的适配角度而言,确实也合适。
其实这个框架的思路,大概也是 KMP / Compose 兼容鸿蒙比较低成本的方向,ArkUI 本身也是响应式构建树,这一方面的可行成本会比较可控,目前我知道已经有一些企业,内部完成了 KMP / Compose 适配到鸿蒙的支持,当然他们用的是更底层的兼容方式,但是这个「转译」其实也算是一个不错的思路,相对成本会更低一些,当然古老的 XML 模式是不用想了,成本太高。
如果鸿蒙的 API 能稳定不再 break 的情况下。
回到 Skip ,在 Skip 内部 Swift 字符串编译后会变为 Kotlin 字符串, Swift 的 class 、structs、enums 和 protocols 会转换为 Kotlin 上对一个的类、枚举和接口,甚至闭包和异步调用也可以兼容。
这意味着,Skip 在和 Android 原生 API 交互时,无论是平台库、第三方库,其实都可以直接调用对应 API,然后提供回调,并来回传递数据,这个过程其实并不需要复杂的桥接,因为本质就是 Kotlin 调用 kt/java 接口。
甚至 Skip 提供了一些简单的实现,可以将 Compose UI 代码嵌入到 SwiftUI ,反之也可以:
VStack {
Text("Hello from SwiftUI")
#if SKIP
ComposeView { _ in
androidx.compose.material3.Text("Hello from Compose")
}
#endif
}
#if SKIP
ComposeView { context in
androidx.compose.foundation.layout.Column(modifier: context.modifier) {
Text("Hello from SwiftUI").Compose(context: context.content())
androidx.compose.material3.Text("Hello from Compose")
}
}
#endif
另外,Skip 提供 Transpilation 用于查看和理解 Skip 的「转译」输出,因为 Skip 「转译」后的 Kotlin 是完全可读的并且可调试的状态,也就是对于 Android 的问题,可以直接在 Android Studio 中运行 Skip Android 应用,并使用 AS 的调试工具进行调试输出。
甚至 Skip 还支持从 Xcode 构建错误消息跳转到 Kotlin 文件,当 Kotlin 编译器输出错误消息时,Skip 的 Xcode 插件会在 Swift 和 Kotlin 源文件中显示为 Xcode 构建错误,点击 Kotlin 文件的构建错误将跳转到有问题的 Kotlin 代码。
从这一点看, Skip 更像是将一个 Swift 项目无缝编译为独立可运行的 Android 项目,也就是当你不想使用 Skip 的时候,你依旧存有 iOS 和 Android 版本的完整源代码可以独立开发,Skip 除了用于在 Android 上提供 Foundation、SwiftUI 等 API 的库外,没有任何必需的运行时组件,也就是当你不想用 Skip 的时候,其实可以相对低成本转化为纯原生开发。
类似思路,如果放到鸿蒙 Next 上呢?如果一个项目编译后,可以直接生成另外一个具有可读性的代码工程,那么是否鸿蒙上也可以通过这种方式,来转化和提升社区的原生开发?
当然,Skip 的这条路肯定也存在很多问题,就像前面说的 uni-app-x 一样,这条路必须存在一定程度的妥协,例如:
- 并不支持完整的语言,阉割是必须的,为了支持 Kotlin 和 Compose ,API 必然需要为了转译器而做删减
- Skip 转译器不能执行 Swift 类型推理以及完整的 Swift 编译器
- 语言差异:例如 Swift 和 Kotlin 处理泛型方式不同,又或者 Kotlin 缺乏 static protocol 要求
另外除了转译器,Skip 还附带了一个 Swift Package Manager (SwiftPM) 到 Android Gradle 项目转换器,Skip 将这些工具捆绑在一起,形成一个 Xcode 构建插件,在 Skip 工具链称为 SkipStone,这一步也帮助完成 Android 端最后打包构建的转换处理。
最后,因为 Swift 的 App 依赖于 Swift 标准库、Foundation 、 SwiftUI 等基础能力库,所以 Skip 开源库提供了 iOS 的 Swift、Foundation、Observation、SwiftUI 等库在 Android 的特定实现, 如 URLSession
和 JSONDecoder
,还有 UI 组件如 NavigationStack
等,Skip 甚至会将 XCTest 单元测试转译为 JUnit 进行测试运行,这一套在 Skip 统称为 SkipStack。
这也算是第一套 iOS 端反卷 Android 的完整跨平台框架,其实这种直接让原生开发支持到另外一端的做法,我个人觉得其实会更受原生开发接受,因为:
- 对比 uni-app、RN、Flutter 需要再学一种语言的场景,它体验更轻
- 对于 Compose MultiPlatform 的场景,它的框架脱离和可独立又更具优势,比如 Kotlin Native 更轻
那么 Skip 有什么问题呢?目前来看Skip 对于国内最大的劣势,就是他是商业框架,有一定程度收费,在 Skip 里 SkipStone 是需要 licensekeys,只有 SkipStack 是免费和开源。
所以我笃定它只能小范围商业合作的流行,但是它的思路还是挺不错的,工程级别的转译需要很大工作量,但是也能让转译后的工程具备独立性,这样为后期可能的独立开发做了很好的基础。
例如原先项目只需要 iOS 开发参与,纯 Native 的 iOS 项目在试水可行之后,通过 Skip 产出的 Android 项目需要进一步开发时,可以直接在已有的工程直接进行 Native 改造,这确实是一个不错的方向。
当然,如果能有类似 Skip 这样完善的框架且完全开源的,并且还适配鸿蒙,或者会是不错的开源方向,或者需要有大厂愿意尝试走通并开源出来共建,大概会比 uni-app-x 具有更大的可能。
参考链接:https://skip.tools/blog/skip-1_0-release/