Frequently Asked Questions
General FAQs
Developer FAQs
What is Skip?
Skip is an Xcode plugin that transpiles your SwiftUI app for iOS into a Kotlin/Compose app for Android. The Skip build process enables you to continuously iterate on both your iOS and Android app with a single unified codebase. To learn more, start with the Skip Tour.
What is a "Transpiler"?
Transpilation is generally defined as the conversion between programming languages that operate at approximately the same level of abstraction. The SkipStone plugin transpiles your app’s Swift code into the Kotlin language, it transpiles your app’s Swift Package Manager project into a buildable Gradle project, and it transpiles your iOS app’s metadata into Android metadata. This is all done automatically by Xcode, the result being that you can build, test, and run your Swift app, and the transpiled Kotlin equivalent app will also be built, tested, and run side-by-side.
What is Skip's current status?
Skip is a technology preview. It has “sharp edges” and missing functionality, but if you are willing to work around the preview’s issues and limitations, you can start using Skip today! Many people are already using Skip successfully, and while it should be considered unstable, it can be used to create production apps on both iOS and Android. The available Foundation and SwiftUI API is still very limited; see the Status page for more details. You are encouraged to seek help on the Skip Discussion Forums or make bug reports or feature requests on the Skip Issues page.
How does Skip compare to other frameworks like Flutter, React Native, Xamarin, and Cordova?
Skip is focused on genuinely native app development exclusively for the two dominant mobile platforms – iOS and Android. A comparison table between the various frameworks can be found on the Skip Comparison Matrix.
What is Swift?
Swift is the officially-recommended language for app development for iOS devices, including the iPhone and iPad. Swift integrates seamlessly with Objective-C, the legacy language for iOS development. For information on Swift, see https://developer.apple.com/swift/.
What is SwiftUI?
According to developer.apple.com, SwiftUI “offers a modern, platform-agnostic approach to building your UI and app infrastructure. With SwiftUI, you specify your interface programmatically and let the system display and update that interface dynamically”. Since debuting in 2019, SwiftUI can already be used to build apps for the iPhone, iPad, tvOS, watchOS, and other operating systems, and has become the recommended way to create new apps for the iPhone and iPad. Skip brings SwiftUI to the Android platform through the SkipStone transpiler and the SkipUI compatibility framework.
What is Kotlin?
Kotlin is the officially-recommended language for app development for Android devices. Kotlin integrates seamlessly with Java, the legacy language for Android development. For information on Kotlin and Android, see https://developer.android.com/kotlin/.
What is Jetpack Compose?
According to developer.android.com: “Jetpack Compose is Android’s recommended modern toolkit for building native UI.” Jetpack Compose, which debuted in 2019, presents a declarative Kotlin API for platform-agnostic user interfaces.
Do I need to know Kotlin to develop with Skip?
You do not need to know any Kotlin in order to build an app with Skip. Skip aims to transparently convert all your Swift code into Kotlin code in a way that makes the Kotlin side invisible to you. However, some degree of Kotlin experience will eventually be needed in order to debug your app on Android.
What are the system requirements for using Skip?
macOS 13 (ARM or Intel) with the latest Xcode, Android Studio, and Homebrew installed. Additional software is required to build and test transpiled projects for Android. See Skip’s installation instructions.
Can the Skip transpiler run on Linux or Windows?
Skip is implemented as a Swift Package Manager plugin, and so is only available on platforms where SPM plugins are supported. Currently SPM plugins are only supported on macOS.
Which parts of Skip are free and which parts are commercial?
The SkipStone transpiler plugin requires a valid license to use for closed-source app developmen. Skip’s ecosystem of libraries, including the core SkipStack modules such as SkipFoundation and SkipLib, are all themselves released under a free and open-source software license, and thus are free for anyone to use, modify, and improve. The Skip frameworks do not include any runtime license checks, meaning that you own both the inputs and outputs of your project; only the build-time transpiler requires a license.
How do I use Skip for free software development?
When every Swift and Kotlin source code file in a project begins with an approved free software license header comment, then the SkipStone transpiler plugin will automatically run in free mode, and no license key will be required to use the tool. You must also have a corresponding “LICENSE.LGPL”, “LICENSE.GPL”, or “LICENSE.AGPL” file in the root folder of your published project, whose contents align with the license header comments in the project’s source code.
The following source code header comment will be sufficient attestation for a .swift
or .kt
file to be used in free mode with the LGPL:
// This is free software: you can redistribute and/or modify it
// under the terms of the GNU Lesser General Public License 3.0
// as published by the Free Software Foundation https://fsf.org
When you run skip init --free --appid=some.free.App project-name AppName
, the generated source files will have this header.
Which FOSS licenses are approved for using Skip in free mode?
The GNU General Public License family of software licenses (LGPL, GPL, and AGPL) are all approved for Skip’s free mode. For information on these licenses, see https://www.gnu.org/licenses/.
The Skip frameworks themselves are licensed under the LGPL, which enables Skip to be used to improve them without needing a license key.
Which FOSS license is recommended for development?
We generally recommend the LGPL, which provides a good balance of flexibility and freedom. LGPL libraries can be embedded in closed-source commercial applications. Many popular software components like WebKit and Qt are distributed under the LGPL.
License warning "Skip trial will expire in N days"
During the Skip tech preview, you can re-request a new 30-day evaluation license by going to the evaluation page.
Can Skip Apps be distributed on the Apple App Store and the Google Play Store?
Yes. Applications built with Skip utilize the user interface toolkits recommended by the platform vendors themselves, and thereby follow the guidelines and principles that are unique to each of these two individual platforms. On the iOS side, the core SkipStack modules can be eliminated from the build (with SkipZero), resulting in an app submission that contains no trace of any Skip libraries whatsoever.
Can I use Skip in a closed-source commercial app?
Yes. Skip’s open-source components are released under the LGPL license, which is the same license used by ubiquitous iOS and Android components like JavaScriptCore and WebKit. LGPL libraries can be linked to by closed-source apps, but any changes to the LGPL libraries themselves must be published freely.
What does it mean it be Genuinely Native?
Skip apps are genuinely native, in that they use the vendor-recommended UI toolkits directly, thereby guaranteeing maximum compatibility, accessibility, and performance. They use SwiftUI directly on the iPhone (“SwiftUI is the preferred app-builder technology, because it offers a modern, platform-agnostic approach to building your UI and app infrastructure.” – developer.apple.com) and Compose on Android (“We recommend using Jetpack Compose if you’re looking to build a new app” – android-developers.googleblog.com).
What is SkipZero?
When a Skip app relies only on the core SkipStack modules (SkipUnit, SkipLib, SkipFoundation, SkipModel, and SkipUI), these libraries can be completely excluded from the app build. This means that you can ship a Skip app for Android and iOS, and there will be no vestiage of Skip on the iOS side at all. One benefit, among many others, is that your app distribution can be miniscule (e.g., the HelloSkip.ipa sample is under 25KB). This also makes Skip easily “ejectable” from your iOS project, in that you can drop the Skip transpiler at any time and continue to have a fully-functional iOS project.
Is Skip a cloud-based service? Do you upload my code to your servers?
No, and no. The Skip transpiler plugin runs locally on your macOS machine as part of the Xcode build process. The plugin is secured using the standard Xcode plugin sandboxing mechanisms that block network and file system access. Neither your Swift nor your Kotlin code ever leave your machine. The only network requirements are for resolving any external dependencies your project has, either on the SPM side for Swift dependenices, or on the Gradle side for Kotlin dependencies.
How is Skip distributed?
The SkipStone transpiler plugin is distributed as a binary executable artifact and driven by the Skip plugin hosted at https://source.skip.tools/skip.git. In addition, the skip
command-line tool must be installed using the Homebrew command: brew install skiptools/skip/skip
. This will install the skip
utility that can be used to create projects and run tests, as well as the prerequisites for being able to perform local Android testing: gradle
, openjdk
, android-platform-tools
, and android-commandlinetools
.
Do Skip or any of the Skip frameworks collect data for the purposes of user tracking?
The Skip transpiler does not collect any data, perform any telemetry, or otherwise “phone home” unless explicitly requested (e.g., running the skip upgrade
command to check for the latest version of Skip). The Skip frameworks, which are all free and open-source (and which can thus be audited externally), also do not collect any telemetry or track users in any way. We provide this notice to help you fill out Apple’s App Privacy Details and comply with Google’s User Data policies.
Note that when installing skip
using Homebrew, they may use telemetry to report the installation event. See the Homebrew Analytics documentation for their explanation and details on how it can be disabled.
How does Skip compare to low-code or no-code app-building technologies?
Skip is the opposite of no-code/low-code offerings. Skip embraces the dominant emerging UI paradigm of declarative user interfaces written in the same language as the platform-native components. This means Swift for SwiftUI, and Kotlin for Compose.
What is the minimum iOS version for Skip apps?
iOS 16+. It is estimated at developer.apple.com that 90% of all devices introduced in the last four years use iOS 16 as of October, 2023.
What is the minimum Android version for Skip apps?
Skip targets Android API level 33 (which is the minimum allowed level for submitting new apps to the Play Store) with a minimum supported version of API level 29. Android Studio estimates that Android API 29 (“Q”; Android 10.0) will run on approximately 72% of active Android devices as of October, 2023 (see developer.android.com).
Why is the first build of my app so slow?
Skip libraries are distributed through SPM as source code, which means that your first build includes building portions of Skip itself as well. Additionally, the first time you build the transpiled Gradle project in order to test and run on Android, the Gradle build system will need to download all of its dependency jars and build tools. This can lead to the initial build of an app downloading many dependencies. The Compose dependencies alone will add around 1GB to the size of the Gradle cache folder, as seen with du -skh ~/.gradle
. But once you have downloaded and cached your project’s dependencies, future builds shouldn’t need to fetch them again.
Does Skip need network access?
Skip itself is a locally-installed Xcode plugin and does not talk to the network, making it suitable for offline use. However, your app’s dependencies will need to be resolved and cached for your app to be built, tested, or run. This means that if you add any new dependencies, either on the Swift side in the Package.swift
, or on the Koltlin side in the build.gradle.kts
(as configured through the module’s Skip/skip.yml
file), you will need to perform a build at least once for the dependencies to be resolved and downloaded.
Does Skip support large codebases?
Skip leverages Swift Package Manager’s support for dependencies between modules, in both local and external git repositories. Skip’s plugin is run individually on each transitive dependency of your project, and the resulting Gradle projects will have these dependencies mirrored. This results in a highly modularizable system, where large codebases can be distributed across multiple modules, each with their individual documentation, test cases, and continuous integration worflows.
What is parity testing?
Skip encourages modularization of large codebases, each with their individual test targets. The command skip test
can be run in a project that contains Skip tests, and both the Swift XCTest
cases and the transpiled Kotlin JUnit
cases will be run, after which the tool will output a markdown table summarizing each of the test results for each of the platforms.
What is SkipStack?
The SkipStack modules are the core compatibility modules that transparently bridge from standard iOS frameworks into their equivalents for Kotlin, Java, and Android.
- SkipUnit bridges the XCTest framework to provide unit testing support through JUnit 4.
- SkipLib bridges the Swift Standard Library for conversion between low-level types and their Kotlin equivalents.
- SkipFoundation provides Java and Android equivalents for the Foundation framework
- SkipModel provides support for Observation through the Compose Runtime framework.
- SkipUI provides an implementation of SwiftUI that bridges to Android’s Jetpack Compose UI components.
The SkipStack frameworks are the fundamental building blocks on which the rest of the Skip ecosystem of libraries is based.
Can I preview the Kotlin that Skip generates?
We provide a “Playground” page at https://skip.tools/playground/ that runs a limited online version of the Skip transpiler in order to preview snippets of transpiled code. When using Skip for development, you can access the transpiled Kotlin it generates at any time.
How much runtime overhead does SkipUI add to the Compose side of the app?
Very little. Many of SkipUI’s views are very simple shims that bridge from their SwiftUI equivalents into Compose, such as Divider.swift simply invoking androidx.compose.material3.Divider
. To support @Environment
and @State
, Skip needs to perform some additinal book-keeping that may have some runtime cost.
What pure Swift libraries can be used by a Skip App?
Skip uses Swift Package Manager to handle source code dependency resolution. Your app’s transitive dependencies will be automatically resolved and downloaded, but they will only be transpiled into Kotlin if the dependent module has a Skip/skip.yml
file. If your project has non-Skip-enabled dependencies, you can either use them from the Swift side only (and seek alternative implementations through the use of #if SKIP
blocks or custom Kotlin files; for an example, see the LottieMotionView implementation). Skip’s constellation of frameworks are expected to provide most functionality that is commonly needed by modern apps, but you are free to develop your own libraries and frameworks, either from scratch, or by forking an existing repository to add Skip support for the library.
How does logging work in Skip?
The SkipFoundation
framework implements the OSLog
module, so an app can log using a Logger
instance, which will output log messages to the Xcode console for the iOS side of the app. For the Android side, log messages are passed to android.util.Log
and can be viewed from the logcat
tab in Android Studio, or by running adb logcat
from the terminal. Note that the print()
function does not send any output to logcat
, so OSLog.Logger
should be the preferred method of logging.
How do resources work in Skip?
The SkipFoundation
framework implements the Bundle.module
function for accessing resources stored in the standard SPM location of Sources/ModuleName/Resources/
. These resources are automatically bundled in the Gradle project, and will be embedded in the resulting .apk
artifact. Note that unlike Foundation on Darwin platforms, the app archive is not expanded on disk for Android apps, but rather can only be accessed using a streaming interface. SkipFoundation handles this transparently for you, so you can load a resource with try Data(contentsOfURL Bundle.module.url(forResource: "SomeResource", withExtension: "ext"))
. However, you cannot perform random access on a resources URL like you can on iOS. This means that embedded resources, such as a .sqlite
database, would need to first be manually extracted to the app’s storage folder before they can be accessed.
How does localization work in Skip?
Localization is not yet implemented, but Skip will eventually support the standard Localizable.xcstrings
translation source file. These files are automatically updated by Xcode 15 to contain any localization-aware string in your app.
This will allow you to have a single translation file that is used by both your iOS and Android app, so that your SwiftUI Text(localized: "Hello!")
will be rendered as “Bonjour!” in French.
How can I use a SQLite database in my Skip App?
We have a SkipSQL framework which provides low-level access to the system-installed SQLite3 library on both iOS and Android.
How can I use a Firebase database in my Skip App?
We are working on a SkipBase framework to enable Firebase integration.
Can I display Lottie animations in my app?
We have a SkipMotion framework framework and a Lottie Demo app available.
Does Skip transpile an app's metadata, icons, and entitlements?
Skip currently only handles the generation of the required AndroidMetadata.xml
, which is populated with the elements from your project’s .xcconfig
file like PRODUCT_NAME
, BUNDLE_IDENTIFIER
, and MARKETING_VERSION
. Other aspects of your Android app, such as icons, must be customized manually for the app, either using Android Studio, or manually in the Gradle project.
How does Skip launch my transpiled app in the Android emulator?
Skip-enabled app projects have an .xcodeproj
generated for them, which includes an embedded script that, as a side effect of running a build of the app target, will assemble and launch the app using the gradle
command. The app will be launched against the first connected Android emulator or device that is found. To customize which emulator should be used, the ANDROID_SERIAL
environment variable can be set to the identifier of the Android device, as seen with the terminal command adb devices
.
How does Skip run my transpiled test cases?
Skip-enabled projects have an XCSkipTests.swift
test case, which is generated as part of the skip init
command (see Getting Started. This test case will use the SkipDrive
module to launch the gradle test
command on the transpiled project. It will then interpret the test results and convert any failures back into XCTest failues, including mapping back the line numbers from the transpiled Kotlin to the originial Swift. This will result in a test failure showing up twice in Xcode: once for the Swift XCTest failure, and one for the Kotlin JUnit failure.
How can I run unit tests against an Android Emulator or Device?
By default, your transpiled XCTest cases are run as Kotlin JUnit 4 tests using the SkipUnit framework, and these tests are run in a local JVM using the Robolectric utilities to mock many Android APIs. If you have a connected Android Emulator or Simulator, you can get the identifer from the command adb devices
, and then set the identifier in the environment variable ANDROID_SERIAL
. This can be done from the command-line with ANDROID_SERIAL=emulator-1234 skip test
. In Xcode you can set this variable in the Scheme’s Run Arguments section, then toggle it on or off to switch between the (faster) Robolectric tests and the (higher-fidelity) Android tests.
Can Skip frameworks be built and tested using continuous integration systems?
Skip framework projects contain built-in support for running parity tests for both the Swift and Kotlin sides of a project. These tests can be included in automated continuous integration workflows to ensure that the tests are always passing. We do this ourselves for the various Skip frameworks, such as the SkipLib Actions, which references our standard GitHub CI workflow.
Does Skip code use garbage collection?
Swift does not use garbage collection, but Kotlin/Java does. Your Swift code that is transpiled into Kotlin will run in the same managed, garbage collected Android Runtime environment as every other Android app. See the developer documentation for details.
Does Skip support Swift language feature ________?
Skip’s Swift support is detailed in the Swift Support Reference.
How does Skip handle ________ difference between Swift and Kotlin?
Many topics related to the differences between Swift and Kotlin are covered in the Swift Support Reference topics.