EAS-196
===
[00:00:00]
Origins of Skip.Tools
---
Leo Dion (host): Hello and welcome to another episode of Empower Apps. I'm your host, Leo Dion. Today I'm joined by Marc Prud'hommeaux. Marc thank you so much for coming on the show.
Marc Prud'hommeaux (guest): Thanks for inviting Leo.
Leo Dion (host): I'll let you go ahead and introduce yourself.
Marc Prud'hommeaux (guest): Yeah, my name is Marc Prud'hommeaux I am one of the, co-founders of Skip.Tools, which is a, development environment and tool set that enables, iOS developers to build their applications for Android.
Leo Dion (host): How did you get started with this idea?
Marc Prud'hommeaux (guest): Well, I've been building apps for, since the very beginning of the App Store, going all the way back to 2008. Mostly iOS, but also some Android. Me and, both my co-founder Abe, ~ ~in this venture, together back in 2008, we actually. Together wrote the first ebook reader for the iPhone called Stanza.
Leo Dion (host): Oh, cool.
Marc Prud'hommeaux (guest): and that was a pretty big hit. And one of the things [00:01:00] after we got, you know, a million users that we kept getting questions about is, you know, when is Android gonna be available? When are you gonna, have an Android version? And we always wanted that. But you know, when you're coming from a really small team, it's, a really big ask to write your app a second time.
For Android. And that's always been the case. And, Stanza wound up getting acquired by Amazon and Abe and I worked for Amazon for a while, and then we sort of went our own ways. Abe worked, at Twitter, head of platform development, iOS, platform development there.
And I, you know, have done various things working on dozens of different app projects. Some really big, like from New York Times and Bose and some fairly small, but. Always, we've been faced with this prospect of. Clients who wanna build their application for iOS first. Because iOS is really, you know, captures the vast majority of the, you know, dollars in terms of, people who spend money, you know, on or through applications.
But Android is the other half of the mobile [00:02:00] ecosystem. And you know, people always come into it, you know, very often saying, okay, we'll design the iOS application first and then Android will be TBD. And then when it comes time to actually implement that Android side, that's when people start making hard decisions and asking tough questions.
Leo Dion (host): Do we bring on a second team? Do we rewrite the whole thing in some cross-platform framework? And there has been no real satisfactory answer up until now. So that's kind of the long roundabout way that we got to identify this, you know, need that. I think all the app developers universally have, having experienced themselves.
How does Skip tools differ from, something like Flutter or React Native or Zain, for instance?
Marc Prud'hommeaux (guest): Yeah, I mean, so those are, have historically been the really big three names in cross-platform app development frameworks. In general, all three of these application development scenarios bring in their own [00:03:00] individual way of building applications. Flutter, which is, packed by Google.
You develop using dart, which is their really bespoke language that is mostly just used for building. Fluter applications, react native, you write it in JavaScript, that's Facebook's, you know, framework and, and Microsoft Zamarin, or more recently Volved as mwe. Yeah. You write in c And so all, all three of these languages and frameworks are really alien for both iOS and for Android.
They're both bringing in their entire, you know, alien development stack. You really need to . Know those languages and really want to develop in those languages. The big difference with Skip is that you write your application in Swift and in Swift UI just using Xcode. You build and you run your app on iOS and Skip on iOS doesn't actually do anything at all.
We don't intrude into the framework. You're writing direct [00:04:00] Swift UI. Using Apple's own Swift UI, where we really differ comes into how we implement the other half of the platform story, the Android half. and that is where Skip takes your Swift code and it builds it for Android. initially the current sort of mature version of Swift 1.0 is that ites all of your Swift code into Kotlin.
and translation is just the process by which we parse. Your Swift code and we convert it into Kotlin code and we output that, and then we build that for Android. and the end result is that on Android we wind up taking, you know, your Swift and turning that into Kotlin. We also wind up taking your Swift UI and turning that into Jetpack Compose.
and Jetpack composed his Androids. You know, modern declarative user interface language, it is the recommended Google recommended way of building Android apps. [00:05:00] and you know, they're very, they're very similar. So it's possible basically to take a Swift UI view and convert that semantic view into the equivalent Android semantic view.
And that's what we do. And so the end result. Is that you don't have, you know, one of these sort of uncanny valley flutter applications where it's kind of mimicking the NATO platform experience and things like that. We have real, you know, honest to goodness native of apps using both of the platforms' common recommended idioms.
Leo Dion (host): Flutter is building directly to machine code, right? It's like kind of using core image to kind of, or C or Objective C to basically write directly on the screen. I'm not sure how React native works. and my experience with React Native hasn't exactly been positive.
So I feel like if it does work, it's amazing, when it does. but I'm not sure if that's [00:06:00] like a. HTML web view or how, do you have an idea how React native works behind the scenes?
Marc Prud'hommeaux (guest): Yeah. Yeah. So, so you're right with flutter. I mean, flutter is actually just drawing every individual pixel on the screen. and then they have, you know, a variety of sort of themes that you can apply. Like they have one that's called the Cupertino theme that sort of makes, you know, sliders look like iOS native sliders and sort of makes text boxes kind of look like text boxes.
you know, enough to sort of . pass a screenshot test and be like, ah, that looks sort of native and that's good enough. react native is different. They actually do wind up rendering onto Native controls, but they're using the React layout, system. They're basically using CSS flex boxes to lay out the components and get them to, you know, show up on the screen in kind of the same way that you'd write a webpage.
But . Instead of rendering to HTML elements, they're kind of rendering to, you know, text fields [00:07:00] and, you know, sliders and, and things like that.
Leo Dion (host): And then Sam or Maui, I would assume is more like, I don't know, kind of compiling directly to an app and then it has a bunch of extensions added on top of it.
Marc Prud'hommeaux (guest): yep. Yeah, that's right. So, yeah, so, you know, react native, they are all JavaScript and it winds up just being interpreted on, on the device and, and they're . A JavaScript, interpreter. but Flutter and Zamarin, they both do compile down to, you know, machine code. and they're shipped as, as binaries, but they also do have garbage collectors built in.
so it is kind of a Java ish scenario on both iOS and on Android.
Leo Dion (host): Okay. If that makes total sense. So as somebody who has never developed an app for Android, I kind of wanted to cover a few things that iOS developers might not know about.
Technical Deep Dive: Swift to Kotlin
---
Leo Dion (host): So let's start [00:08:00] off by saying, what are like some major differences that you've seen with Kotlin and Swift?
Marc Prud'hommeaux (guest): Well, you know, they really come from the same . next generation kind of language push. You know, Kotlin is really replacing, has replaced Java for Android development, just as Swift has more or less replaced Objective C development for, for iOS. And both of these languages, you know, are very, you know, heavily stress, type inference.
and, you know, declarative design, Kotlin is, you know, I always say if you squint hard enough, Swift looks just like Kotlin. you know, you can say, you know, var X equals A, B, C, you know, funk do thing, and then, you know, arrow return value. There's a couple of fairly minor syntactic differences, but, you know, you can, you can sort of [00:09:00] cobble together a Hello world main program in Kotlin and it looks a lot like.
you know, Swift. so it's, it's similar enough that you can imagine, you know, just writing a regular expression or something and taking your Swift program and turning into Kotlin. the more advanced things like generics, and converting value types like structs and things like that, some of these don't have an exact equivalent in Kotlin, and that's where the.
The translation of the Swift into Kotlin starts to get really, really complex. and that's, that's where the Skip plugin does all the heavy lifting for you.
Leo Dion (host): So is there, like, they don't have generics quite the same way that that Swift does.
Marc Prud'hommeaux (guest): Yeah. Simple, basic generics work more or less the same. You can have a collection that does, you know, on a generic type,
Leo Dion (host): Okay. I could see how that would be kind of a pickle.
Marc Prud'hommeaux (guest): Yeah. But, and, and generics on protocols do wind up getting implemented pretty diff fairly differently on interfaces in lin interfaces are, are, [00:10:00] are the equivalent there. and then on top of all of this, the fact that Kotlin is built on top of Java and is running in a JVM, regardless of where you're running it, be it on Android or on a server or on your desktop, Java has historically made these very controversial decision to erase your types. So they do this thing called type erasure. So those types don't actually exist to the knowledge of the runtime environment. And so that means that we have to tack on a good amount of metadata in order to be able to accomplish some of the things that come naturally with, Swift, where you do always know, you know what the generic type is at, at runtime.
Leo Dion (host): Are there any performance disadvantages with using Swift and then having it with all the additional metadata and such?
Marc Prud'hommeaux (guest): Not really. You know, we, we attempt to . you know, distill things down, compile things as idiomatically as we possibly can. you know, Kotlin in general, it is a garbage [00:11:00] collected environment. and they have no native value types there. There's no equivalent to a structure in Enum, in, in Swift. you know, so, you know, what we have to do is we have to wind up.
Translating, you know, your structs and your enums your value types into classes in Kotlin in such a way that it preserves the copy and write semantics that Swift offers you.
Leo Dion (host): Okay.
Marc Prud'hommeaux (guest): and so that is gonna be not as efficient as the Swift version. I mean, it's, it's just, it's not, it's turning into, it's running, you know, on A JVM, it's garbage collected.
but that being said. We don't really have never really encountered performance issues with it because in general, Android is designed to accommodate this sort of . You know, additional memory, overhead, you know, the higher watermark, the garbage collection and things like that. the statistic that I read is that on average the equivalent sort of quality Android phone [00:12:00] to, you know, the, the, the, their iOS version, you know, the premier premium, you know, levels and the, and the mid levels they want, they tend to have twice as much RAM as the equivalent iPhone.
Version does. and that is largely to accommodate, you know, the additional memory overhead that you need for Java and
Leo Dion (host): Right, right. That makes total sense. So let's move on to the UI part. What's the big differences between Jetpack Compose and Swift UI?
Marc Prud'hommeaux (guest): well. As with, you know, I say Squint hard enough and Swift looks like Kotlin squint hard enough, and Swift UI looks like Jet Pack Compose Yeah, just went a little harder. because, you know, the, the structure of Jetpack Compose, you know, Swift. Sets up views in a hierarchy of these structs
Leo Dion (host): Mm-hmm
Marc Prud'hommeaux (guest): have a body.
and the body might have, you know, a vs stack that contains a text field and a slider and a button. and Jeff had composed you more or less have that same sort of declarative outline of your views, [00:13:00] differences that they're done in, global functions. And top
Leo Dion (host): Oh, okay.
Marc Prud'hommeaux (guest): rather than infuse.
Yeah. And so those functions are the things that sort of track the state access that takes place inside of them. and marks those, once the state gets marked as dirty marks those, as being needed for what they call recomposition. and recomposition is essentially where the view knows that ~it needs to Yeah, exactly.~
~It needs to, ~it needs to redraw.
Leo Dion (host): I was gonna say a big thing is like you're losing a lot of the power generics and do they even have a DSL in JPAC Compose?
Marc Prud'hommeaux (guest): They not quite like as good as Swift does. they're really working more with what they have in Kotlin, but they do have a composed compiler. you mark your functions as what they call composable. and that winds up being run as a Kotlin compiler plugin, once it is
Leo Dion (host): So it's kinda like a macro in a way.
Marc Prud'hommeaux (guest): Yeah.
Leo Dion (host): yeah.
Marc Prud'hommeaux (guest): it's a lot [00:14:00] like a macro.
And so these composable functions, they have additional metadata that's tacked onto them. Basically a context that's being passed through that has, you know, hooks that grant access to all of your state, to, you know, all of your environment, all the things that it needs to know in order to be able to, you know, know when you need to recompose these, these views.
Leo Dion (host): So how, like, so I did actually build an app. I followed through on the example. and it was like, I, I recently ordered a pixel for a 'cause. I wanted something cheap and like small to work with and, built a app and it was amazing. How does like the build process work on Android different from like Xcode build and deploying to a simulator or device?
Marc Prud'hommeaux (guest): Right, right. So, you know, again, . Android has all these mirrors to what we're, you know, you know, we have in the iOS development world, you know, Swift has Kotlin, Swift UI has Jetpack [00:15:00] Compose. In addition, Swift Package Manager has an equivalent in the Kotlin world called Gradle. and Gradle is a ancient build tool that, you know, goes back really, you know, to to early times used to be done in Groovy.
Now it's, it's native DSL is Kotlin itself. Similar to how Swift Package, Swift Files, yeah. Are implemented in Swift, Gradle implements those in in Kotlin. and so you write in whatever build logic that you need and it has its own DSL for declaring dependencies and declaring multiple modules. And you know, more or less everything you have in a package Swift you can accomplish and, build gradle dot kts file.
and so what the. You know, skip Stone plugin does automatically as every time you rebuild your application, you know, we, we convert your Swift Kotlin, we convert your Swift UI to JetPack compose. We also take your Swift package manager package Swift, along with any dependencies, and we convert that into [00:16:00] a mirror tree of Kotlin Gradle.
project builds. and so you wind up having this parallel structure that is automatically derived from your Swift build every time, every time you build. So then you have this, this, you know, forest of, of Gradle build files that, ~you know, ~you could run manually if you wanted to. You just run great old build in, in the correct directory.
But what what we do is as part of the template application that you create when you run the skip and net command, we add a build phase into Xcode such that when you launch your application, it winds up invoking gradle, launch debug, on the trans pile version of the Gradle project so that every time you build and run your application on the iOS simulator, on the iOS device.
The equivalent transpiled up to date Gradle, project is [00:17:00] compiled and run on your attached, Android simul, emulator, or Android device.
Leo Dion (host): so ever have you ever used like tourist?
Marc Prud'hommeaux (guest): Yes.
Leo Dion (host): So I mean, it sounds like basically their stuff is set up all in Kotlin, similar to how tourist has the whole exit project set up in Swift, essentially, and then you could go from there. it's, that's what I'm hearing. I don't know, but it sounds a lot like that, which is, which is kind of cool.
Marc Prud'hommeaux (guest): Yeah. Yeah, a little bit. Now we don't, we don't use tourist on the side of how we create the Xcode build file.
Leo Dion (host): Right, right. No, I just mean like the fact that you can create an Xcode project using Swift, you can create an Android project using Ling. So I guess that's what I'm, I'm using the parallels there.
Marc Prud'hommeaux (guest): Yeah, exactly. And that has the benefit too, that you know, not only do you, can you build and run this from Xcode, which is really the common [00:18:00] development cycle that iOS developers will want to use, but you can also take that same, you know, build Gradle dot kts. And you can invoke it.
You can open it in, in Android, ID like, Android Studio or IntelliJ. and all of these have built in support for Kotlin, Kotlin Rale files. And so that's how you can basically take that, take that application and open it in Android studio, and then you can have access to all of the Android studio tools that you need.
Like, you know, analyzing the size of the generator artifact, running the debugger, and things like that.
Leo Dion (host): so the. I first, I think I've heard of the project, the skip tools before, but really intrigued me was the, post I think you had on LinkedIn where you were showcasing Biff packages that are compatible. And I'm a big fan of Swift Package Manager is imperfect as it is, and it was cool to see like all these libraries that were available like to use already on Android.[00:19:00]
how does Skip, how does it employ Swift Package Manager throughout its. It's development and we'll talk about external LI or internal libraries that Skip has. But, how does it use Swift, Swift packages? in, its, in the, the development and piling operation
Marc Prud'hommeaux (guest): So, you know, we always say this project wouldn't have been possible a couple years ago. It was really the advent of Swift package manager build plugins that made all of this possible. and build plugins are, you know, basically a, you know, plugin line that you add to, your project dependency that is, you know, defines an action that can get run.
Whenever you perform a project build. and that's really what unlocked the ability for us to hook right into Swift package manager's, build process and be able to do things like, you know, parse all of your Swift files and be able to, to convert them into, into Kotlin on, on every build. [00:20:00] and so that really also makes it independent of Xcode at all.
You know, you can run. This process, you know, the build process, just using Swift package build, on the command line, which is great for continuous integration as well because, you know, for all of our packages, both our core packages like the Skip UI and Skip Foundation packages, but also for our external packages like Skip Firebase and Skip SQL and things like that,
Leo Dion (host): Okay.
Marc Prud'hommeaux (guest): you can just build and test as part of a GitHub action, which is, you know, has been fantastic for us for quality control.
Leo Dion (host): So, so like I build a lot of my apps using Swift Package Manager is basically the code base and. something like Truist to then bring that in and use that to build an app. how would I, like, let's, how would I move forward with, with some of my current apps to get those over to Android? if everything is basically in Swift Package Manager, [00:21:00] should I still employ something like tus and then, and then run skip tools on top of that?
Or what would you recommend?
Marc Prud'hommeaux (guest): Probably what we generally recommend is that, you create or initialize basically a blank skip project using skip a net and what, what that winds up doing is it creates, so the core of everything is a Swift package manager package Swift. But when you create, an application project using. Skipping it and passing the app Id.
it additionally creates both a, Darwin folder and an Android folder. And the Darwin folder create, creates a, you know, app named Xcode Project. and that's kind of an empty shell of a project. Really all it does is it references that Swift Package manager. Top level package. so in some ways it's kind of an unusual Xcode project because really it's just all it's doing is wrapping, wrapping a SPM project, and then [00:22:00] providing additional metadata like, you know, the application icon and you know, the entitlements and all of the, all the extra stuff that.
Needs to go into building a real application. but it is really sort of a hollow, kind of a hollow application, a hollow project. It doesn't have, I think it has one source file just 'cause it needs a main method. but you know, other than that it just really references the Swift package manager module.
so generally, and, and that's sort of a, a very customized xcode project that it creates. So we generally recommend that people . Create one of these kind of empty projects and then bring in their code, sort of piecemeal into the application. and then it might be a iterative process, right? Because not, maybe not everything is going to transp pile out of the box.
Leo Dion (host): And so, you know, sometimes it won't be working on the very first build and run. but we provide you with a lot of guidance and, you know, warnings and, and things like that. If, if it doesn't build at first.
Where would you [00:23:00] recommend somebody be like this, this tool is great, but there's a few spots where you might wanna actually write some Kotlin code. Where would that be the best fit, I guess?
Marc Prud'hommeaux (guest): Yeah, so we have, in our docs is a platform customization guide and there's a variety of ways of doing this, of, of basically dropping in custom Kotlin. And there's a lot of reasons why you would need to do so. You know, there are plenty of, you know, we trans, we translate, you know, a lot of Swift UI into jet pack compose, and we translate a lot of your foundation.
Libraries into the equivalent Android libraries, for example, like URL and, you know, file manager calls and things like that. but there's always gonna be things that are very iOS specific that aren't gonna just automatically translate into the Android world. and in those cases, you know, the easiest solution is just to drop
The equivalent Kotlin call right into your Swift code. [00:24:00] and the way that we accommodate that is we have these, pre-processor blocks that are just like pound if skip, and if you put code in there, X code will ignore it and the iOS build will ignore it. But we, it's part of the skip stone plugin will process that and pass that over to the generated kotlin.
So you can actually just drop raw Kotlin right into . The middle of your Swift code, and then be able to be able to work with it. and it looks pretty weird at first, just sort of like you're using Java idioms, right? You have Java package names and you know, you have sort of some Kotlin, you know, syntax.
but Xcode is happy to ignore it, on the, on the Swift side. And so that's really the sort of quickest way to basically say there's this iOS specific call. There's no . obvious, you know, translation available for it. So I'm gonna do this thing on the Android side and I'm gonna make, you know, what I deemed to be the equivalent call and then [00:25:00] work with that.
that's really the, the first level way of, of dealing with that, of, then there's the second way, which is a little more elaborate. You know, sometimes it's not like one or two lines. Sometimes ~you have~ a whole, you know, big Kotlin file of logic that you don't wanna . Paste into Xcode, you know, and, and sort of massage until, you know, the, the syntax works.
You know, lines are quite right. So you can also just drop in a Kotlin file into a skip folder in your Swift package manager package. and then that again, will get ignored on the Swift side, on the iOS side. but that will just be brought straight into your Kotlin build. and then you can reference that from code within if skip blocks.
Leo Dion (host): Oh, okay. So you could like build a class in Kotlin and then reference that class in your if skip. Okay. Very cool.
Marc Prud'hommeaux (guest): that's right. And then, and then there's, there, there's a third, you know, the sort of next level up [00:26:00] is actually having a Kotlin dependency. you know, I mentioned Skip takes your . Your sort of network of, ~ ~of Swift package manager projects and converts it into a Kotlin equivalent. It only does that for packages that support the skip stone plugin for basically packages where you had planned on having it work with Skip.
~ ~
you can also have any dependencies you want on the iOS side, like you can depend on projects that don't have any knowledge of Skip or anything. ~ ~but those won't . Exist on the Kotlin side. They won't be transpired, they won't be, you know, referenced. ~ ~however, what you can do is in the skip side, you can add dependencies just like you can on the Swift side, ~ ~dependencies
Leo Dion (host): Kotlin libraries,
Marc Prud'hommeaux (guest): Exactly, yeah.
And there's a, there's sort of an
Leo Dion (host): their equivalent?
Marc Prud'hommeaux (guest): Their equivalent is called Maven dependencies.
Leo Dion (host): so it's, yeah, which is the Java one.
Marc Prud'hommeaux (guest): Yeah, exactly. And so you basically, you, you know, basically say I depend on, you know, [00:27:00] com, Google Firebase, you know, colon 1.5 0.3, you put that in your skip, there's a skip configuration file on a per Swift package manager module basis called Skip Do yaml.
~you ba ~you basically list those dependencies in there and then in the derived Kotlin, Gradle . Project, it will have the dependency on those libraries. And so then inside of, say if skip blocks or inside of, you know, your raw Kotlin, you can just import those packages and you can use them directly.
Swift on Android Working Group
---
Leo Dion (host): As of the today, the record day of recording, Giannis had posted the, Swift on Android work group, and. I wanted to ask about about that, but before I do, is there, I do a lot of. Stuff with Lin like Aun or Linux as well as the Apple platforms, and I know we've had Windows stuff for quite a while. is there already any, like [00:28:00] pre-processor directives or anything with available Mac? not the available macro, but the available attribute, that are specific to saying that a certain method is or is not available on Android. That are either compiled time or runtime, I guess outside of Skip,
Marc Prud'hommeaux (guest): Yeah. Yeah. So there is, so there are. The Android work has been going on for, you know, many years by, you know, not just us, but a large community of people. There are some pre-processor checks. You can do FOS, Android, then do this and you know, else do that. There's not currently, unfortunately, 'cause that'd be really useful for us.
There's not currently any way to annotate a, a function as being, or class as being available or not available at Android, similar to the way that you can do it on . Tv, VOS, this is not available. Watch os this is available. that'd be a great addition. Something that not just Android people, but Linux and Windows people would also find useful.
Leo Dion (host): Yeah. I mean, even Linux people like I, I end up having to do like if [00:29:00] can import, is my work around for that sometimes.
Marc Prud'hommeaux (guest): Yeah, that's what we do as well. Yeah, we do. If can import, Android is the name of the module for, for Android, you know, packages, so you can do, if, can import Android. I, I wrote a blog post recently that's gotten some traction, mentioning that Swift everywhere. Package about, you know, how you can get your package working on native, native compiled Android.
and, you know, 90% of the time is just adding in a, if can import Android, then import Android. Elif can import Darwin, import Darwin Elif can import
Leo Dion (host): Right, right, right.
Marc Prud'hommeaux (guest): yp, import Eucalyps and Portugal. And
Leo Dion (host): Yeah. Yeah, yeah, yeah. That's, that's a really good call. I like, the one I'll do is like, if can import 50 Y, for instance, is a
Marc Prud'hommeaux (guest): Exactly. Yeah. Yeah.
Yeah.
Leo Dion (host): So, yeah. And then like on the Swift package, can you, I, I bet you can't even say what Android version you support in the Swift
Marc Prud'hommeaux (guest): No, you can't say, but yeah, no, [00:30:00] it's, it's still, all that stuff is really limited to Darwin platforms right now. But that's one of the things that we really want this android working group to, to really get underway with, with helping push is, you know, expanding those to, to support the other platforms.
Leo Dion (host): Well, let's, let's get into that. What, what are you looking forward to when it comes to the Swift, and Swift on Android work, work, reading group?
Marc Prud'hommeaux (guest): So I should prefix this by saying that everything I've been talking about thus far has really been Swift, skip 1.0 where everything is transp compiled. and what, you know, that takes your Swift and turns it into Kotlin, and builds it just like a regular . You know, Android app, a hundred, you know, everything going into it is gonna be Kotlin or Java code.
There's no native code at all. and that has been working, you know, great so far. But as I had mentioned, there are some limitations in transpiration. You know, there are some limitations around, [00:31:00] generics. there are some, you know, there there's some sharp edges. Like you can't have retroactive conformance to protocols for types outside of your current module.
You know, there's kind of a list of things that are just . Just impossible to accomplish with translation. so that's one shortcoming of translation. Another one is that in order to depend on another Swift package from your . Trans pilot skip code. That package also needs to be aware of Skip. It needs to have the skip stone plugin being run and things like that.
and not every package is gonna want to do that. You know, not every package is thinking about Android or, you know, really wants to bring in that dependency.
Transpiled vs. Natively Compiled Swift
---
Marc Prud'hommeaux (guest): Um, and so for the past, about the past year, we've been working on integrating natively compiled Swift on Android side by side with the trans piloted.
Swift on Android and that that sort of complicates everything a little bit because sometimes your Swift is turned into Kotlin and [00:32:00] compiled with the Kotlin compiler. Other times your Swift is just compiled directly to Android using the Android, Swift tool chain. and then what Skip winds up doing is, using the skip fuse package, it automatically and transparently builds a bridge.
between your Transpi Swift and your Compiled Swift. so that for, you know, the, the common example is, right now if you run, skip a Knit for a, you know, new, new application package and pass native to it, what it will do is it'll create an application, sort of a Hello World application that's like a little cred app, with create, read, update, delete on a little Jason file.
and without Native, that will create two modules. A, you know, a UI module with all the Swift UI and sort of a data model, module, with the, you know, model handling code where it, you know, is a observable [00:33:00] view model and it, you know, reason writes from adjacent file and things like that. so in pure transpired mode, those are both.
done in Transpile, Swift that will turn into, into Kotlin. When you run that in native mode, what that will do is the Swift UI is currently still transpile into Jetpack Compose, but the view model code is actually gonna be compiled directly to Android. nice. then . They communicate back and forth as you know, using Swift observability, using the bridge that winds up getting automatically built.
Leo Dion (host): Okay.
Marc Prud'hommeaux (guest): So what that grants you is your view model code, your, all of your model code that can have any dependency on Native Swift that you want. It can use Alamo Fire, it can use, you know, the point free company, you know, Swift snapshot testing. It can use basically any of these packages that are already building natively for Android and unlocks that entire huge ecosystem, [00:34:00] you know, growing ecosystem of, pure Swift packages that you can, you can start taking advantage of.
Leo Dion (host): That's pretty amazing. you think that's like pretty much the future is going with compiled as opposed toed?
Marc Prud'hommeaux (guest): Yeah, in order to give real reach to all of your code, you know, to have it be sort of true, a hundred percent compiled Swift, We do think that that is probably the future, for, you know, for simple apps or apps that don't have a lot of dependencies, things like that. you know, . People can perfectly, you know, stick with the transpile process that has been working so far.
You know, we've shipped half a dozen apps and there are other people, you know, many other people that are shipping apps today that, that use that approach and that approach has a few advantages of its own right. It, you know, not having to embed all of the Swift libraries means it's a much smaller binary.
Shipped on Android, debugging. That's a much easier story when it's all [00:35:00] done in Kotlin and, and Java. You know, if you have a crash in Swift and debugging that on Android, there's currently some challenges that we're gonna be working with this working group to overcome. where, you know, you see these ma.
Leo Dion (host): I mean, are we talking Android support on Xcode? Like I, I don't even know how you would get there. Right? If you're gonna step through a piece of pre transpired Swift, right.
Marc Prud'hommeaux (guest): Yeah. Yeah, I mean, we'd love that. You know, we've, we've, you know, communicated with Apple that that'd be a great feature. I don't see that happening right away.
Leo Dion (host): right,
Marc Prud'hommeaux (guest): So, so, you know, you can, you know, if you open your project in Android studio and you run it in a debugger, you do get some native support for that debugger.
But you know, you've probably seen mangled Swift names. You know, in, in the past, and they're not easy to Digest or understand, and you can't jump to the line and, you know, so, so there are challenges with purely native code. but overall, you know, we feel that [00:36:00] as this technology evolves, which is currently in still in early access tech, you know, tech preview, release, but it's, you know, available and people are using it now.
We think the benefits really outweigh the disadvantages because it is, it is real Swift, so you have true value types. You're really, you know, you're running real native compiled code. It's gonna be more memory efficient, and you have access to this entire, you know, galaxy of, of wonderful Swift packages.
Leo Dion (host): Going back to that question I had earlier, earlier about how does it differ, like we're talking about being a little bit more like flutter in a way, as opposed to like the transation, which I don't think anybody really does, right?
Marc Prud'hommeaux (guest): Yeah, no, to my knowledge, I think there have been a couple of academic experiments with translation, but to my knowledge, you know, we're really the only ones that are doing that level of, you know, you can develop a full app using transation.
Leo Dion (host): one thing I wanted to come back to is, as far as the [00:37:00] translation is concerned, would anyone ever want to edit the Transp piled code or would they ever want to commit it to their repo? Or is it something that should be done way behind the scenes? And don't touch it. Don't look at it.
Marc Prud'hommeaux (guest): We're happy to have you look at it. Actually, you can just open it right in X code and, you know, look at them side by side and, and we have some map back line numbers when there are, you know, the errors and things like that back to the original Swift. So we're happy to give you access to it.
Leo Dion (host): But
Marc Prud'hommeaux (guest): don't, we don't read backend changes that you make to it.
You know, we, we mark those files that read only, and if you unmark them and make a change to it, they're gonna get lost the next time you build.
Leo Dion (host): So the intention is to just let the bill tool use it as part of the process. But don't, I mean, almost now that I'm thinking about it, it almost seems like, like Babel, I guess would be a good comparison on, on an NPM or, or node where it's like, oh, you know, this. Used to have [00:38:00] browsers, right, that didn't have TypeScript support, for instance, and you'd use something like that to it.
So it can actually be used in in the browser. Browser essentially. It almost, this is kind of what it sounds like a bit,
Marc Prud'hommeaux (guest): a good equivalent is like TypeScript JavaScript. You generally don't expect to be able to mess with the resulting JavaScript, and then, you know, affect the original TypeScript. Now all that being said though, you know, skip is a commercial tool and you know, we sell the Transer plugin. However, . And the output of the skip process is still your own code.
Leo Dion (host): Right. Right.
Marc Prud'hommeaux (guest): we have a mechanism for exporting your project. It's command, the skip export, it takes your entire project and it creates a fully buildable runable Android. I. Project, you know, that uses Jetpack Compose and, and everything, and it's completely separate from needing any of the skip, you know, build tools.
And that's what we call adjustability. That basically means like, say you decide down [00:39:00] the road, you don't want to use Skip anymore. You, you know, you developed version 1.0 of your app and you know, maybe you decided I'd rather just go my own way and have a Kotlin team and take your app and go with that.
You're perfectly free to take that resulting exported project. And hand it off to your Kotlin team, and they can go their own way with them.
Leo Dion (host): right. ~Exactly. Exactly.~
Marc Prud'hommeaux (guest): ~won't, ~it won't be pulled back in to your single, you know, Swift source base, but it is your own code to do with whatever you want.
Leo Dion (host): Yeah. Awesome. I just, I wanna cover a couple of questions that we got from the audience. Danny Bahar asked about, ~I'll say what he said. ~curious how Skip handles 50 Y UI kit representable ice cream. Skip doesn't transpose map Kit. PDF Kit Pencil Kit. A way to write Lin code for certain parts of your app in order to fill those apps.
Looking forward to the pot, looks amazing. So you kind of answered some of the stuff already. [00:40:00] I'll just kind of paraphrase. So UI Kit, is that supported at all?
Marc Prud'hommeaux (guest): No, not the vast, but a little bit of it is like, you know, we have some UI color and UI font sort of the things that are needed for support. But the ui UI view representable, we don't have direct support for that because we don't transp pile UI kit views. But what we do have is an equivalent on the composed side called Composed view.
and so when you want to sort of, interface . With more legacy views. You know, Swift UI, you have Legacy UI kit you want to interact with. Same thing on Jetpack Compose. They have their legacy Android views, not all of
Leo Dion (host): What is that?
Marc Prud'hommeaux (guest): it's, they just call it Android views. . There's no, there's no other name for it.
They're the old school, sort of. You write XML, you know, views and you build them up. But there's a huge . Pool of these that have have, you know, evolved over, you know, a decade.
Leo Dion (host): right.
Marc Prud'hommeaux (guest): and so there's the equivalent in Jetpack Compose where you can, you [00:41:00] know, insert old school, you know, legacy Android views using what's kind of the Android version of UI view, representable.
and so what you wind up doing and, and the way that we handle things like say, . well actually MAP Kit recently did get a UI view, but . Pretending for a moment didn't, or say, sorry. WK web view, that's a really common one. what you would do is you'd use this if skip block mechanism where you'd say, you know, if not, skip, in other words, if you're running on iOS, do the UI view representable and you put in a web view in there, and then you do all the stuff you need to do with sort of a, a complicated and large task.
And then on the Android side, in the else, if Skip, You would use a compose view and you would drop in a Android web kit, web view, you would do sort of the equivalent, you know, management shuffling around of, of state and, and dealing with all that stuff. and it's something that people do very [00:42:00] commonly using Skip, because that's, that's one of the real selling points is that, you know, unlike frameworks like, you know, flutter or React native, we're, we're making a bridge as a
Gigantic and complex and very involved task. You can just drop this stuff right into your Swift file and you can, you know, start iterating from there and see it come right up on your . On your Android screen. So even though it might be a little bit, you know, complex and daunting at first, you know, you can get pretty far just by, just by dropping, you know, code in there.
Skip Showcase and Practical Applications
---
Marc Prud'hommeaux (guest): We have a, we have an app that's actually available on the App Store, in the Google Play Store, called Skip Showcase. and, and that is more or less a list of, I think all of the Swift UI. You know, views, view types, you know, there's a, a navigation list for, you know, sliders and date pickers. I'm actually, I'm looking at it right now, and gesture, recognizers
Leo Dion (host): this is on the, the Google App Store or the,
Marc Prud'hommeaux (guest): It, it's on,
Leo Dion (host): the Google Play [00:43:00] Store.
Marc Prud'hommeaux (guest): Yeah, so it's on both the App Store and the Play
Leo Dion (host): Okay.
Marc Prud'hommeaux (guest): and it, it's, it is really useful when people are evaluating Skip, because you can bring this app up, skip showcase on both, and you can be like, okay, what does a picker look like on both of these? And you can see exactly how the picker appears, you know, in the user or the progress view.
Leo Dion (host): So I wanted to ask, what if you add something that is not supported in Android? What will end up showing up in Android?
Marc Prud'hommeaux (guest): So it is whatever you wind up doing in the, if not skip block, ~like maybe~
Leo Dion (host): ~Well, no. ~What if you forget to? What if you have, just like throw in a map view in Swift y and then you transpire what's gonna end up happening?
Marc Prud'hommeaux (guest): It would, well, if you didn't guard it inside a NIF skip block, then there would be an error once you
get
Leo Dion (host): a compilation error.
Marc Prud'hommeaux (guest): a compilation
Leo Dion (host): Okay, cool. I was just wondering how, at what point the line would you get a warning, so that's good to know.
Marc Prud'hommeaux (guest): so we have, we have a couple. We have the at the Build . Processing time. Basically when the build plugin runs, when you kind of doing the pre-build, we do have a, a bunch of mechanisms [00:44:00] for warning you as well when something is missing. so for example, if there is some Swift DI view that we don't yet support, we mark that in skip as being unavailable.
So you'll very quickly get a nice, a message that says. This API is not available. Maybe a suggestion for what you can do. if you don't hit that, then you will wind up when it tries to do the gradle build and build for Android, you'll wind up with a compilation error, which might not be quite as friendly as the ones that we surface earlier on.
Leo Dion (host): Right. I, as long as it's not something that you're gonna put on the Google place or, and find out that
Marc Prud'hommeaux (guest): Right. Oh, yeah. No. Yeah. So unlike say like React native, where you know JavaScript, hope you tested every possible runtime branch, you know, you still do have a compiler going on here, so you're not gonna just like wind up missing something and having a crash or a crazy error at,
Leo Dion (host): Right, right. I did wanna, I, I, I do wanna give you a chance to mention that there are some extra frameworks [00:45:00] available with Skip. so stuff like Skip web for doing specific web views and things like that are available. so
Marc Prud'hommeaux (guest): Yeah, we've got.
Leo Dion (host): you, you do have some stuff to kind of make that bridge. easier.
Marc Prud'hommeaux (guest): Yeah, we have a whole, a bunch of packages that are, you know, sort of commonly used by applications. You mentioned skip web. That's really common for dropping in an embedded web browser. And actually that's a good package. And all of these are free and open source on GitHub under the Skip tools. Skip tools repository list.
That's actually a pretty good one to take a look at. If you're curious about how you have these parallel implementations between Android and iOS, because that is essentially just doing what I described where you have a UI view Representable on the . iOS side and you have a composed view on the, on the Android side.
but yeah, so you know, we have like, that, we have Skip sql, which runs on top of, you know, SQL Light. So you can, you know, write to SQL databases. We have Skip Firebase, [00:46:00] which is actually a pretty interesting one because Skip Firebase, you know, we, we obviously did not reinvent . The Firebase APIs on the Swift side, we, we just run directly against the Google Firebase Swift SDK that they provide.
we don't actually interpose ourselves at all. You just are calling the Google APIs directly. and then on the,
Leo Dion (host): Is Fire bakes built into Android?
Marc Prud'hommeaux (guest): no, no, it is a separate, it's a separate package and, and
Leo Dion (host): really?
Marc Prud'hommeaux (guest): Yeah, so, so it does interface with Google Mobile Services, which is part of many Android distributions, but is also a separate, somewhat separate component because for example,
Leo Dion (host): not like cloud kit where everybody gets cloud kit when
Marc Prud'hommeaux (guest): Right. No, it's not, it's not baked in a hundred percent of the places. so you know, also in general, like Jetpack Compose is not part of Android as well. Like all of these things, unlike say, Swift UI, which is bundled as part of the operating system, all of these things are really brought [00:47:00] in at build time and bundled as part of your app, of your application package.
And so Firebase is one of those that, that is built in, that is bun, sorry, bundled in, not built in. and what we wind up doing with our Skip Firebase support is that since Google is pretty good actually about having these two APIs be very similar in terms of just like type names and method names and things like that.
Our skip support for that. Really all it is, is just some really simple pass through wrappers where we have a sort of a skip side Swift type that is like firebase, you know, connection, firebase analytics, Firebase auth, that really just passes these calls straight through to their Kotlin equivalents, which are in many cases named exactly the same thing.
So it actually winds up being a fairly rote exercise to enhance that package. So, yeah, so that's, that's another good one. we have, another good example is Skip Bluetooth, which is almost [00:48:00] completely user contributed. you know, we had, we started the package a long time ago, but never actually implemented something, but just a couple months ago, someone came along and said, I need, you know, Bluetooth, you know, support through Skip.
And they wound up just implementing a very large swath of the, the, ~ ~iOS Bluetooth. SDK on top of the Android equivalent Bluetooth services.
Leo Dion (host): Very cool. ~ ~I wanted to get one question, one other question outta the way from Adam Hill. ~ ~he's asking, I'd like to know if there's any timeline on trans piling arbitrary macros. just not apple specific ones. So I guess. I mean, I, I could try to answer this question, but I would ~assume~ there is no timeline because we're moving over to compiling. so you do support macros, though? It does sound like
Marc Prud'hommeaux (guest): No, none. the, not on, not on the transation side. So I think the question is maybe [00:49:00] alluding to the fact that we do have built-in support for some of the built-in macros
Leo Dion (host): Right? That's what I meant. Sorry. Apple's macros are supported, but if you create your own macro, translation.
Marc Prud'hommeaux (guest): Yeah. I mean it's actually, we'd love to have support for that, but there's actually limitation on the Swift Build plugin system. We don't get access to the, macro
Leo Dion (host): what I was gonna ask. Right. Right.
Marc Prud'hommeaux (guest): So there's not really any way that we can. Support arbitrary user written macros. however, in the Native Swift compilation and the skip fuse, you know, version on your model side, we do support it.
So it, because it's just regular Swift. So the answer is that in, in the trans pile world, we only support a subset of the, you know, of the ones that we've decided, you know, to handle like observable. on the compiled, side of Swift, we support any macros.
Leo Dion (host): Okay. That makes total [00:50:00] sense. Yeah. I'm surprised you guys don't have, I mean, they're already doing any transation in a, not transation, it's probably not the right term, but I would assume you would've access to the code after the macro had been applied, but it sounds like you don't.
Marc Prud'hommeaux (guest): Yeah, no, we only get it before, ~you know, ~we've, we've raised it . With Apple and we have not yet heard an answer to, to, that request. I, I don't entirely see how they could do it, actually. I mean, unless they're to change the entire order of how things are, run in the build process. but it would, it would, it has been a shortcoming so far.
~You know, ~one of the reasons why we are definitely pursuing the compiled angle as well as the trans compiled angle.
Leo Dion (host): Right, right. so if somebody wanted to use Skip, do they need to do to get started? How much does it run for? And yeah.
Marc Prud'hommeaux (guest): So, yeah, so we have a very generous, free plan. Basically we have an indie plan, where you can, [00:51:00] use it to build, ~you know, ~one app. As long as you're sort of a small business, or ~you know, ~a small group of people, Buildship one app for free. So you don't have to use it, you don't have to pay anything at all.
if you are a small business, then it is a annual, subscription, and it is, 2 99 a year. and then a professional for sort of a large organization. it's 9 99, 999 a year on a per developer basis.
What is FOSDEM?
---
Leo Dion (host): Um, before we close out, I did wanna ask you, about FOSDEM. You spoke at this conference. I don't think a lot of people know what FOSDEM is, especially here in the us. but it's very popular. I know a lot of people spoke, from the Swift community at it. what is it, what you speak about?
Marc Prud'hommeaux (guest): so
Leo Dion (host): why were Swift people there?
Yeah.
Marc Prud'hommeaux (guest): Foss is a annual, free [00:52:00] open source software convention in Brussels. this was actually my first year there. it was a blast. It's huge and it's totally free to attend. it was at the campus of a, a university in, in Brussels. and. ~You know, ~there's all sorts of different tracks.
There's, you know, tracks about JavaScript, there's tracks about, you know, a lot of server side stuff. ~ ~more or less, anytime that there's free and open source software and ecosystem, you can get one of these speaker rooms. And these speaker rooms have various tracks. ~ ~and this was the first year there was a Swift track, ~ ~that was going on.
That was, ~ ~that was very cool. There were a bunch of . Very interesting talks, only some of which I was able to attend. but I, I think that was really exciting for sort of Swift to make inroads into, you know, a community where historically people have sort of looked at it as a corporate Apple only just iOS building kind of language and opened it up to more like, oh wow, you can build, you know, a Linux server process using Swift.
You can run around Raspberry Pi, [00:53:00] you know, things like that.
Leo Dion (host): what did you speak on?
Marc Prud'hommeaux (guest): So I actually didn't speak on the Swift track. I spoke on an entirely different track. and it was actually about building App Stores, specifically about, ~ ~the alternative app, all app marketplaces in the European Union, which is a project that I've been working on for a while. Actually unrelated to Skip, but is using Skip technology in order to create, a single universal app marketplace for people to be able to distribute open source applications.
Leo Dion (host): Oh, that's awesome. We'll have to put a link to that in the show notes as well.
Marc Prud'hommeaux (guest): Yeah, I see, I see. App Fair Project. and it's, It's coming along. It's it's, we basically, that's, that's how we are currently publishing our current example, skip applications, through the App Store. So it's, it's very nearly ready for, you know, ingesting other people's open source apps and being able to provide them to the entire world.
[00:54:00] And that, and, and that's really, you know, the source of passion for me that, you know, really caused me to wanna be able to create Skip is that . We wanna make apps that reach the entire world, right? So, you know, not just all the devices, which for all intents and purposes is iOS and Android. That's essentially a hundred percent.
but also all languages and all abilities. So we have really good support for, ~ ~localization, inter internationalization in skip applications. We take your XC strings translation files,
Leo Dion (host): I saw that. It's amazing.
Marc Prud'hommeaux (guest): Yeah, we convert those over to Android. we have really good support for the accessibility APIs and Swift UI.
so, you know, with just a single code base for the first time, really you can take a single sort of premium . Polished iOS application, and you can reach the entire global population, which is like 90% of all adults have one of these two smartphones. and that's what really makes it exciting for me [00:55:00] is the, the possibility that a single creator can finally reach, you know, the entire market space without needing multiple teams and coordination between, you know, a lot of different developing groups and things like that.
Leo Dion (host): Yeah, that's amazing. Marc it was so cool to talk to you today about Skip. I played around with it. It's pretty amazing. Pretty happy that I can build an app in Swift and post it on the actual Android phone. So I was super happy about that. thank you. Thank you for coming on.
Marc Prud'hommeaux (guest): Thanks so much for having me, Leo. It was really, ~ ~it's really been a blast.
Leo Dion (host): where could people find you online?
Marc Prud'hommeaux (guest): skip Do Tools is really the, primary way of, of reaching me and, and the project. ~ ~and then on the about page, you can, ~ ~you can see the links to my various social media, ~ ~outlets.
Leo Dion (host): I will have links to the Skip showcase, the, your talk from fos and the alternative store that you, ~ ~are working on. And yeah, definitely take some time. Download skip tools. Give it a try. It's pretty fun. ~ ~[00:56:00] Thank you for ~joining~ me for today's episode and, ~ ~if you are watching this on YouTube, please subscribe and really appreciate it.
And if you're listening to this on a podcast player, ~ ~please post ~a review~ if you really enjoyed this episode. Thank you so much ~and we~ will talk to you ~again.~ Bye everybody.