Episode Transcript
1
00:00:00,001 --> 00:00:06,000
So I feel slightly outnumbered today on today's episode of the podcast,
2
00:00:06,000 --> 00:00:12,800
because, well, for something a little novel that we used to do at the very beginning,
3
00:00:12,800 --> 00:00:15,300
but we haven't done for a little while, is we have a guest on the podcast.
4
00:00:15,300 --> 00:00:23,100
But before we introduce our guest, I'm actually going to pass the baton to Sven,
5
00:00:23,100 --> 00:00:27,000
because I feel a little outnumbered in people who speak French today.
6
00:00:27,000 --> 00:00:33,000
And I'm not going to attempt the pronunciation of our guest's name.
7
00:00:33,000 --> 00:00:35,200
So, Sven, would you like to introduce our guest?
8
00:00:35,200 --> 00:00:38,800
I was wracking my brain while you were talking, thinking,
9
00:00:38,800 --> 00:00:40,800
what would Marc and I have in common?
10
00:00:40,800 --> 00:00:43,200
And I'm giving away part of his name already.
11
00:00:43,200 --> 00:00:48,900
It's Marc Brudomont, who's joining us today to talk about Swift on Android.
12
00:00:48,900 --> 00:00:54,500
You've completely dumped this introduction on me, Dave. Thank you.
13
00:00:54,500 --> 00:01:01,000
Well, I didn't want to embarrass myself with my attempt at the pronunciation,
14
00:01:01,000 --> 00:01:04,000
because I am not a French speaker, unfortunately.
15
00:01:04,000 --> 00:01:05,600
I wish I was, but I'm not.
16
00:01:05,600 --> 00:01:08,700
Hello, everyone, and fantastic pronunciation, Sven.
17
00:01:08,700 --> 00:01:11,000
It's better than I think I've ever heard it.
18
00:01:11,000 --> 00:01:11,900
Thank you.
19
00:01:11,900 --> 00:01:13,500
I was also very impressed.
20
00:01:13,500 --> 00:01:19,200
I knew the reason I dumped it on Sven was I knew he'd do a good job with that.
21
00:01:19,200 --> 00:01:23,900
But welcome. Thank you so much for joining us.
22
00:01:23,900 --> 00:01:25,300
Yeah, thank you for having me.
23
00:01:25,300 --> 00:01:33,200
So, I think the best place to get started is for you just to give a little introduction of who you are and what you do.
24
00:01:33,200 --> 00:01:38,400
Yeah, okay. Well, my name is Marc Brudomont, as we would say in English.
25
00:01:38,400 --> 00:01:42,300
And yeah, I am a developer.
26
00:01:42,300 --> 00:01:46,700
I've developed in a wide variety of languages and technologies over my career.
27
00:01:46,700 --> 00:01:52,600
But past, you know, 15 odd years, I've been predominantly an iOS developer.
28
00:01:52,600 --> 00:01:57,600
And I've started a company a couple of years ago called Skip.
29
00:01:57,600 --> 00:02:08,100
And the vision is to enable people to write their applications in Swift and be able to deploy them to both iOS and Android.
30
00:02:08,100 --> 00:02:13,700
It's really nice to see Swift growing into multiple other platforms.
31
00:02:13,700 --> 00:02:23,800
And it will be no surprise that we chatted with Marc before we added Android support to Swift Package Index,
32
00:02:23,800 --> 00:02:26,700
which we did a couple of months ago now.
33
00:02:26,700 --> 00:02:42,300
Because Marc and the Skip Tools team had made an independent website that was starting to test compatibility with Android packages
34
00:02:42,300 --> 00:02:45,400
or Swift packages compatibility with Android.
35
00:02:45,400 --> 00:02:47,900
And you were running that as a separate site, weren't you?
36
00:02:47,900 --> 00:02:50,900
Yeah, yeah, yeah. It was a Swift Everywhere.
37
00:02:50,900 --> 00:02:56,900
And it was just sort of running GitHub Actions that was more or less trolling through, you know, the popular packages
38
00:02:56,900 --> 00:03:00,500
and seeing does this build for Android? And if not, what are the errors?
39
00:03:00,500 --> 00:03:06,800
And then very often I would go through and I would try to resolve the errors and submit pull requests to the projects.
40
00:03:06,800 --> 00:03:14,100
And it was kind of a personal project to be able to promote the usage of the Swift Android SDK
41
00:03:14,100 --> 00:03:20,500
and be able to kind of build up more compatibility with some of the popular projects out there.
42
00:03:20,500 --> 00:03:28,100
And as you can now see on the site, we do have, well, we actually added two platforms at the same time.
43
00:03:28,100 --> 00:03:32,100
We added both Android and WASM compatibility checking.
44
00:03:32,100 --> 00:03:37,100
But just to stick on the Android for a little bit, and we'll talk more broadly in a second,
45
00:03:37,100 --> 00:03:46,600
but apart from checking the build logs that we do publish when we do all our platform builds,
46
00:03:46,600 --> 00:03:49,600
so if you haven't seen this feature of the Swift Package Index,
47
00:03:49,600 --> 00:03:54,600
if you look at the full build results of any package, you can then click through to the build log.
48
00:03:54,600 --> 00:04:00,600
And if there was a failed build, we will attempt to show you the build log.
49
00:04:00,600 --> 00:04:05,100
So apart from looking at those logs, is there anything that package authors can do
50
00:04:05,100 --> 00:04:11,100
to help themselves become more compatible with Android?
51
00:04:11,100 --> 00:04:17,600
Yeah, well, in general, the first step, so to step back a little bit,
52
00:04:17,600 --> 00:04:22,100
the Swift Android SDK is a cross-compilation SDK.
53
00:04:22,100 --> 00:04:27,600
So it's similar to the Static Linux, the MUSEL SDK and the WASM SDK.
54
00:04:27,600 --> 00:04:35,600
And it's a SDK that adds on to the host tool chain in order to allow you to build on a host platform,
55
00:04:35,600 --> 00:04:41,100
in other words, Mac or Linux or Windows, for another platform.
56
00:04:41,100 --> 00:04:46,600
So for example, with the Static Linux SDK, you can build on macOS for Linux.
57
00:04:46,600 --> 00:04:55,600
And with the Android SDK, you can build on macOS or Windows or Linux and cross-compile to Android.
58
00:04:55,600 --> 00:05:05,600
And in general, building for Android, you run into a lot of the similar issues as you would building for Linux.
59
00:05:05,600 --> 00:05:12,600
Very often, if there's like a low-level libc kind of function or something like that you're using,
60
00:05:12,600 --> 00:05:22,600
where maybe you would import Darwin on macOS or iOS, you would need to import glibc on Linux.
61
00:05:22,600 --> 00:05:28,600
That's usually with a conditional like if can import Darwin, if can import glibc.
62
00:05:28,600 --> 00:05:31,600
Android adds another one to that, which is Android.
63
00:05:31,600 --> 00:05:40,600
So you can cover a huge swath of those sorts of issues by just doing, you know, if can import this, if can import that,
64
00:05:40,600 --> 00:05:42,600
and then conditionally importing them.
65
00:05:42,600 --> 00:05:49,600
Generally speaking, if your package can compile for Linux, it's almost certainly going to be a pretty short,
66
00:05:49,600 --> 00:05:52,600
you know, small amount of work in order to get to build for Android.
67
00:05:52,600 --> 00:05:58,600
You're actually getting at a question that was sort of forming in my head as you two were talking,
68
00:05:58,600 --> 00:06:02,600
is how different is the Android SDK to Linux actually?
69
00:06:02,600 --> 00:06:07,600
If you were to boil it down, it sounds like it's almost as if there was a different kind of,
70
00:06:07,600 --> 00:06:11,600
you know, we have this Muzzle and glibc types of Linux.
71
00:06:11,600 --> 00:06:15,600
Is Android sort of, could you consider it to be a variant kind of like those?
72
00:06:15,600 --> 00:06:20,600
Yeah, yeah. So Android is Linux. It's just not GNU Linux.
73
00:06:20,600 --> 00:06:23,600
They have a different libc, they call it bionic.
74
00:06:23,600 --> 00:06:24,600
Yeah.
75
00:06:24,600 --> 00:06:28,600
And it's pretty compatible. Like they have almost all the same functions.
76
00:06:28,600 --> 00:06:34,600
You know, you can call abs and cosine and, you know, fopen, fclose, things like that.
77
00:06:34,600 --> 00:06:39,600
But generally speaking, it is not exactly the same.
78
00:06:39,600 --> 00:06:45,600
That's why you have a different set of headers that you import for the kind of low-level stuff.
79
00:06:45,600 --> 00:06:51,600
And so, yeah, it's very similar to sort of the difference between the static Linux SDK
80
00:06:51,600 --> 00:06:57,600
and actually compiling for Linux, where in one you import glibc and another you import Muzzle.
81
00:06:57,600 --> 00:07:03,600
And so, I mean, was there a particular itch you wanted to scratch yourself
82
00:07:03,600 --> 00:07:06,600
when you started delving into Swift on Android?
83
00:07:06,600 --> 00:07:11,600
What was sort of the motivation for you to try and do this?
84
00:07:11,600 --> 00:07:16,600
Well, the overarching goal is essentially to be able to, you know,
85
00:07:16,600 --> 00:07:21,600
the holy grail of mobile app development is to be able to use the same language
86
00:07:21,600 --> 00:07:24,600
to build an application for both platforms.
87
00:07:24,600 --> 00:07:31,600
And this is something that, you know, I have always been dissatisfied with the current state of affairs.
88
00:07:31,600 --> 00:07:35,600
You know, there's been a lot of iterations of this sort of thing, you know,
89
00:07:35,600 --> 00:07:38,600
in the olden days we had, you know, like Cordova and things like that
90
00:07:38,600 --> 00:07:42,600
that were just sort of like, you know, web views that you can code in JavaScript.
91
00:07:42,600 --> 00:07:46,600
More recently, the popular packages are things like Flutter and React Native
92
00:07:46,600 --> 00:07:51,600
where you, you know, write your app in Dart or JavaScript.
93
00:07:51,600 --> 00:07:54,600
But these all have, you know, a tremendous number of shortcomings
94
00:07:54,600 --> 00:07:57,600
that I think are pretty well understood.
95
00:07:57,600 --> 00:08:02,600
And they don't really embrace the native platform APIs.
96
00:08:02,600 --> 00:08:08,600
So, you know, the very high level goal was we want to allow you to write an application
97
00:08:08,600 --> 00:08:10,600
in a single language.
98
00:08:10,600 --> 00:08:13,600
And we love Swift. Swift is a fantastic language.
99
00:08:13,600 --> 00:08:16,600
We think it's ideal for application development.
100
00:08:16,600 --> 00:08:22,600
You know, they say it's, you know, all the ease of Java with all the efficiency of C.
101
00:08:22,600 --> 00:08:25,600
It's really ideal for this scenario.
102
00:08:25,600 --> 00:08:30,600
So that's really where we come from is we want to enable people to build their applications
103
00:08:30,600 --> 00:08:34,600
for the two major mobile operating systems out there.
104
00:08:34,600 --> 00:08:37,600
And everything else is really a result of that.
105
00:08:37,600 --> 00:08:41,600
You know, the whole joining the Android workgroup and all our iterations on the SDK
106
00:08:41,600 --> 00:08:46,600
and the tool chain and all of that is in service of this larger goal.
107
00:08:46,600 --> 00:08:49,600
And how practical is that today?
108
00:08:49,600 --> 00:08:51,600
It's very practical.
109
00:08:51,600 --> 00:08:57,600
People are using skip to build and ship applications, you know, currently.
110
00:08:57,600 --> 00:09:01,600
It does all work the sort of official--
111
00:09:01,600 --> 00:09:07,600
So we ourselves, skip, are publishing our own tool chain right now, our own SDK,
112
00:09:07,600 --> 00:09:12,600
that is essentially the exact same SDK that is eventually going to be the official one
113
00:09:12,600 --> 00:09:15,600
that's published on swift.org.
114
00:09:15,600 --> 00:09:18,600
And we also have a lot of tooling that is built on top of it
115
00:09:18,600 --> 00:09:23,600
because just having a cross-compilation SDK is only one small real piece
116
00:09:23,600 --> 00:09:27,600
of the whole picture of actually building an application with, you know,
117
00:09:27,600 --> 00:09:30,600
graphical elements and integration with system APIs and things like that.
118
00:09:30,600 --> 00:09:31,600
Of course, yeah.
119
00:09:31,600 --> 00:09:35,600
But, yeah, no, it's up and running today.
120
00:09:35,600 --> 00:09:37,600
Things work really well.
121
00:09:37,600 --> 00:09:39,600
There's kind of two modes that we run in.
122
00:09:39,600 --> 00:09:42,600
We have something called skip light, which was our first iteration before we had
123
00:09:42,600 --> 00:09:48,600
the whole Android tool chain, where instead of actually compiling your Swift on Android,
124
00:09:48,600 --> 00:09:51,600
we transpile the source language to Kotlin,
125
00:09:51,600 --> 00:09:55,600
which is Android's sort of its own native development language.
126
00:09:55,600 --> 00:09:56,600
Right.
127
00:09:56,600 --> 00:10:00,600
And then that has really evolved into the current offering,
128
00:10:00,600 --> 00:10:03,600
which is called skip fuse, which takes those two concepts,
129
00:10:03,600 --> 00:10:06,600
the transpilation in order to integrate with Kotlin APIs,
130
00:10:06,600 --> 00:10:10,600
plus the native Android SDK, and bridges them all together
131
00:10:10,600 --> 00:10:14,600
so that you have one-- you have all the benefits of writing all your applications
132
00:10:14,600 --> 00:10:18,600
on Swift, but you can still talk to all of the Android APIs,
133
00:10:18,600 --> 00:10:20,600
which are all in Java and Kotlin.
134
00:10:20,600 --> 00:10:21,600
Right.
135
00:10:21,600 --> 00:10:23,600
So actually-- and I wanted to clarify that.
136
00:10:23,600 --> 00:10:27,600
When you use Swift on Android to develop an app, you are actually--
137
00:10:27,600 --> 00:10:29,600
like the GUI is a native GUI, right?
138
00:10:29,600 --> 00:10:36,600
It's not like Qt on Mac that sort of has UI elements that look Mac-like
139
00:10:36,600 --> 00:10:39,600
but aren't actually-- to my knowledge.
140
00:10:39,600 --> 00:10:41,600
Last I checked, it was sort of a different--
141
00:10:41,600 --> 00:10:46,600
it was made to look like Mac UI but wasn't truly Mac,
142
00:10:46,600 --> 00:10:48,600
was redrawn effectively.
143
00:10:48,600 --> 00:10:53,600
But this you're saying is actually-- this is using actual Android native UI elements.
144
00:10:53,600 --> 00:10:54,600
Is that right?
145
00:10:54,600 --> 00:10:55,600
Yeah.
146
00:10:55,600 --> 00:10:59,600
So these are sort of genuine native user interfaces on both platforms.
147
00:10:59,600 --> 00:11:03,600
And that's the thing that we feel like no one has really succeeded with.
148
00:11:03,600 --> 00:11:06,600
You look at Flutter apps and things like that,
149
00:11:06,600 --> 00:11:09,600
and they draw the pixel, they paint the pixels onto a canvas,
150
00:11:09,600 --> 00:11:13,600
and they kind of mimic iOS with their Cupertino theme,
151
00:11:13,600 --> 00:11:16,600
and they mimic Android with their Material theme.
152
00:11:16,600 --> 00:11:23,600
But pretty quickly, even a non-technical user identifies the scrolling is not--
153
00:11:23,600 --> 00:11:24,600
Yeah, you can always tell.
154
00:11:24,600 --> 00:11:27,600
--right, the little delay, the font rendering.
155
00:11:27,600 --> 00:11:30,600
I mean, just a million things that are so obviously apparent,
156
00:11:30,600 --> 00:11:33,600
maybe not from screenshots, but the minute you start using an application.
157
00:11:33,600 --> 00:11:34,600
Yeah.
158
00:11:34,600 --> 00:11:36,600
And so that was really a hard requirement for us
159
00:11:36,600 --> 00:11:40,600
is that it needs to be actually native on both platforms.
160
00:11:40,600 --> 00:11:42,600
And I think it's the right requirement as well
161
00:11:42,600 --> 00:11:50,600
because I think it is really just very important for that platform look and feel,
162
00:11:50,600 --> 00:11:53,600
especially the feel, actually, more than the look,
163
00:11:53,600 --> 00:11:56,600
that it is using the native libraries.
164
00:11:56,600 --> 00:12:04,600
And it's an approach that Salim used with the Windows integration libraries.
165
00:12:04,600 --> 00:12:07,600
They were--when I first saw that project,
166
00:12:07,600 --> 00:12:11,600
I kind of assumed that it was going to use SwiftUI
167
00:12:11,600 --> 00:12:14,600
and then kind of mock up the SwiftUI on Windows,
168
00:12:14,600 --> 00:12:16,600
but actually it's not that at all.
169
00:12:16,600 --> 00:12:23,600
So the Swift WinRT packages hook into the native Windows APIs
170
00:12:23,600 --> 00:12:27,600
rather than trying to do cross-platform UI.
171
00:12:27,600 --> 00:12:28,600
Yeah, exactly.
172
00:12:28,600 --> 00:12:32,600
And we just feel that, you know, you look at all the best-in-class applications,
173
00:12:32,600 --> 00:12:35,600
even the ones made by Google and Facebook
174
00:12:35,600 --> 00:12:40,600
who run the Flutter and React Native projects respectively,
175
00:12:40,600 --> 00:12:42,600
they all write their applications twice,
176
00:12:42,600 --> 00:12:45,600
once in Swift and Objective-C for iOS
177
00:12:45,600 --> 00:12:48,600
and another time in Java and Kotlin for Android.
178
00:12:48,600 --> 00:12:52,600
Because of that, you just cannot get that premium feel
179
00:12:52,600 --> 00:12:56,600
if you're not using the native toolkits.
180
00:12:56,600 --> 00:12:59,600
And where, you know, Skip kind of has an easy time
181
00:12:59,600 --> 00:13:04,600
is that on the iOS side, we're just using an intermediated SwiftUI.
182
00:13:04,600 --> 00:13:08,600
Like, we don't stand in between you and, you know, real Swift
183
00:13:08,600 --> 00:13:10,600
because we're not really doing anything on iOS.
184
00:13:10,600 --> 00:13:13,600
It's on Android where we take your SwiftUI
185
00:13:13,600 --> 00:13:16,600
and we translate that into the equivalent native calls
186
00:13:16,600 --> 00:13:18,600
using what's called Jetpack Compose,
187
00:13:18,600 --> 00:13:21,600
which is kind of Android's equivalent of SwiftUI,
188
00:13:21,600 --> 00:13:24,600
and which is their recommended, you know, native toolkit
189
00:13:24,600 --> 00:13:26,600
for building Android applications.
190
00:13:26,600 --> 00:13:29,600
So we really only have half that problem to tackle,
191
00:13:29,600 --> 00:13:31,600
which doesn't mean that it's easy.
192
00:13:31,600 --> 00:13:33,600
It's actually extremely difficult in many ways.
193
00:13:33,600 --> 00:13:36,600
But it means that we only have that side of it
194
00:13:36,600 --> 00:13:39,600
to really have to, you know, nail down all the features
195
00:13:39,600 --> 00:13:40,600
and all the polish.
196
00:13:40,600 --> 00:13:44,600
Right, and that sounds like there's a bit of gluing together
197
00:13:44,600 --> 00:13:47,600
that you need to do in instrumenting the APIs, right?
198
00:13:47,600 --> 00:13:49,600
And that sort of leads me to the question,
199
00:13:49,600 --> 00:13:51,600
how ready is--are there any types of apps
200
00:13:51,600 --> 00:13:53,600
that this is particularly suited for?
201
00:13:53,600 --> 00:13:58,600
Are there any gaps you still have to sort of, you know,
202
00:13:58,600 --> 00:14:01,600
fill in, or what's the overall state
203
00:14:01,600 --> 00:14:05,600
and what kind of apps you could be targeting?
204
00:14:05,600 --> 00:14:09,600
Yeah, yeah, so we have a very large percentage
205
00:14:09,600 --> 00:14:12,600
of the SwiftUI API covered where we, you know,
206
00:14:12,600 --> 00:14:15,600
translate it into the equivalent Jetpack Compose
207
00:14:15,600 --> 00:14:17,600
and native Android UI.
208
00:14:17,600 --> 00:14:21,600
If your app can use primarily stock SwiftUI components,
209
00:14:21,600 --> 00:14:24,600
you know, things like line of business applications,
210
00:14:24,600 --> 00:14:25,600
you know, things like that,
211
00:14:25,600 --> 00:14:28,600
then you're going to have a really good experience
212
00:14:28,600 --> 00:14:30,600
because you don't really have to go off the rails.
213
00:14:30,600 --> 00:14:33,600
You can just write it as if you're writing your iOS app
214
00:14:33,600 --> 00:14:35,600
and then Swift takes, you know,
215
00:14:35,600 --> 00:14:39,600
Skip takes over and handles that for Android.
216
00:14:39,600 --> 00:14:41,600
It's when you have a lot of sort of custom components.
217
00:14:41,600 --> 00:14:43,600
If you need to drop down to, like, UIKit
218
00:14:43,600 --> 00:14:46,600
or need to use a lot of Apple-only frameworks,
219
00:14:46,600 --> 00:14:49,600
that's where you need to sort of delve into
220
00:14:49,600 --> 00:14:51,600
some of Skip's extensibility options
221
00:14:51,600 --> 00:14:53,600
for being able to implement some of that yourself.
222
00:14:53,600 --> 00:14:55,600
And that's when you need to start thinking about
223
00:14:55,600 --> 00:14:57,600
doing a little bit of your own work in Kotlin,
224
00:14:57,600 --> 00:15:02,600
which is kind of a leap in terms of the complexity
225
00:15:02,600 --> 00:15:04,600
of integrating this stuff.
226
00:15:04,600 --> 00:15:07,600
Right, and it sounds like you have escape hatches,
227
00:15:07,600 --> 00:15:09,600
so you're not lost.
228
00:15:09,600 --> 00:15:11,600
You don't have to abandon your product
229
00:15:11,600 --> 00:15:12,600
if there's stuff you can't do.
230
00:15:12,600 --> 00:15:15,600
You can still escape hatch out on the Android side
231
00:15:15,600 --> 00:15:18,600
into native Kotlin and obviously on the SwiftUI side.
232
00:15:18,600 --> 00:15:22,600
Escape hatch out into the UI and still have the same app.
233
00:15:22,600 --> 00:15:24,600
You probably just if-def it somehow.
234
00:15:24,600 --> 00:15:26,600
I guess you have a mechanism to--
235
00:15:26,600 --> 00:15:27,600
Yeah, exactly.
236
00:15:27,600 --> 00:15:30,600
We have a series of sort of escape hatches
237
00:15:30,600 --> 00:15:35,600
that go in incremental complexity degrees,
238
00:15:35,600 --> 00:15:38,600
but the simplest one is the one that we're most proud of,
239
00:15:38,600 --> 00:15:41,600
which is you can just type, you know, #ifskip
240
00:15:41,600 --> 00:15:44,600
and just drop some Kotlin right into your Swift.
241
00:15:44,600 --> 00:15:45,600
Oh, nice, okay.
242
00:15:45,600 --> 00:15:47,600
And then, you know, else if not.
243
00:15:47,600 --> 00:15:53,600
And then the Xcode build plugin will handle taking that,
244
00:15:53,600 --> 00:15:54,600
extracting it from your Swift,
245
00:15:54,600 --> 00:15:56,600
putting it out in the Kotlin,
246
00:15:56,600 --> 00:15:57,600
and then building the bridge for you
247
00:15:57,600 --> 00:15:59,600
so that the native Swift is able to communicate
248
00:15:59,600 --> 00:16:01,600
back and forth with the custom Kotlin
249
00:16:01,600 --> 00:16:03,600
that you drop into your code.
250
00:16:03,600 --> 00:16:05,600
And then you can use that as the entry point
251
00:16:05,600 --> 00:16:09,600
to accessing the whole ecosystem of Kotlin libraries
252
00:16:09,600 --> 00:16:12,600
that exist in the Android world.
253
00:16:12,600 --> 00:16:14,600
You mentioned SwiftPM plugin there.
254
00:16:14,600 --> 00:16:17,600
Is there some machinery that is particularly useful
255
00:16:17,600 --> 00:16:20,600
from the whole compiler and SwiftPM tool chain
256
00:16:20,600 --> 00:16:22,600
that makes this possible at all
257
00:16:22,600 --> 00:16:24,600
without a lot of extra instrumentation?
258
00:16:24,600 --> 00:16:28,600
Yeah, yeah, no, the full build plugin system,
259
00:16:28,600 --> 00:16:30,600
you know, Skip wouldn't be possible without it
260
00:16:30,600 --> 00:16:32,600
because the way Skip works is, you know,
261
00:16:32,600 --> 00:16:35,600
you just work in Xcode and you develop your app
262
00:16:35,600 --> 00:16:36,600
and you build and run it
263
00:16:36,600 --> 00:16:39,600
and it launches it on the iOS simulator as normal,
264
00:16:39,600 --> 00:16:41,600
but it also launches it side by side
265
00:16:41,600 --> 00:16:42,600
on the Android emulator.
266
00:16:42,600 --> 00:16:45,600
So you can iterate on these two things side by side
267
00:16:45,600 --> 00:16:47,600
and you don't have to really--
268
00:16:47,600 --> 00:16:48,600
you don't have to launch any other tools,
269
00:16:48,600 --> 00:16:49,600
you don't have to do anything,
270
00:16:49,600 --> 00:16:52,600
and it's the magic of the build plugin that does all this.
271
00:16:52,600 --> 00:16:55,600
You know, every time you change any of your Swift,
272
00:16:55,600 --> 00:16:57,600
the build plugin picks it up,
273
00:16:57,600 --> 00:16:59,600
it does all the necessary bridging,
274
00:16:59,600 --> 00:17:01,600
it writes out, you know,
275
00:17:01,600 --> 00:17:03,600
any additional massaging it needs
276
00:17:03,600 --> 00:17:06,600
to be able to launch the Android tool chain
277
00:17:06,600 --> 00:17:07,600
to build it natively,
278
00:17:07,600 --> 00:17:09,600
packages up your application,
279
00:17:09,600 --> 00:17:11,600
puts it on the device or the emulator
280
00:17:11,600 --> 00:17:12,600
and then runs it.
281
00:17:12,600 --> 00:17:15,600
That's really all handled by the build tool plugin.
282
00:17:15,600 --> 00:17:18,600
So without that, it really would not have been--
283
00:17:18,600 --> 00:17:20,600
it would not have been nearly as smooth a process.
284
00:17:20,600 --> 00:17:23,600
You'd need to be having extra steps
285
00:17:23,600 --> 00:17:24,600
where you go to the command line
286
00:17:24,600 --> 00:17:26,600
and launch external tools and things like that.
287
00:17:26,600 --> 00:17:27,600
- That sounds great.
288
00:17:27,600 --> 00:17:30,600
- And coming at this from the other side,
289
00:17:30,600 --> 00:17:33,600
there is, of course, Kotlin Multiplatform.
290
00:17:33,600 --> 00:17:35,600
How do you feel about Kotlin Multiplatform?
291
00:17:35,600 --> 00:17:38,600
- Yeah, so we've worked with it actually quite a bit.
292
00:17:38,600 --> 00:17:39,600
Skip, in some modes,
293
00:17:39,600 --> 00:17:42,600
does actually integrate somewhat with Kotlin Multiplatform,
294
00:17:42,600 --> 00:17:46,600
but for the most part, you can kind of view Skip
295
00:17:46,600 --> 00:17:48,600
as the inverse of Kotlin Multiplatform
296
00:17:48,600 --> 00:17:52,600
where they have a mechanism where, you know,
297
00:17:52,600 --> 00:17:55,600
they take Kotlin and they build and, you know--
298
00:17:55,600 --> 00:17:59,600
it's just your regular Kotlin in the Android development side,
299
00:17:59,600 --> 00:18:00,600
so it's not doing anything there,
300
00:18:00,600 --> 00:18:04,600
but when you deploy on iOS, what it does is
301
00:18:04,600 --> 00:18:08,600
it creates essentially Objective-C wrappers
302
00:18:08,600 --> 00:18:11,600
around that Kotlin, and it compiles it for iOS,
303
00:18:11,600 --> 00:18:14,600
and then you sort of have an XE framework
304
00:18:14,600 --> 00:18:16,600
that you hand off to your iOS developers,
305
00:18:16,600 --> 00:18:17,600
and you can use it to implement
306
00:18:17,600 --> 00:18:20,600
sort of the business logic of your application.
307
00:18:20,600 --> 00:18:23,600
You'll still be writing the two user interfaces separately,
308
00:18:23,600 --> 00:18:25,600
one in Android Studio and one in Xcode,
309
00:18:25,600 --> 00:18:29,600
but you'll be able to share a lot of the low-level logic.
310
00:18:29,600 --> 00:18:34,600
So in many ways, Skip is kind of the inverse of that process
311
00:18:34,600 --> 00:18:37,600
when all you're using Skip for is sharing business logic.
312
00:18:37,600 --> 00:18:42,600
But then in addition to that, you can also use Skip
313
00:18:42,600 --> 00:18:44,600
for the whole sort of vertically integrated
314
00:18:44,600 --> 00:18:46,600
user interface side as well,
315
00:18:46,600 --> 00:18:48,600
which Kotlin Multiplatform doesn't have
316
00:18:48,600 --> 00:18:50,600
quite the same experience around.
317
00:18:50,600 --> 00:18:51,600
Sure.
318
00:18:51,600 --> 00:18:54,600
I think the other thing we wanted to talk about today
319
00:18:54,600 --> 00:19:00,600
was the recent announcement and founding
320
00:19:00,600 --> 00:19:03,600
of the Swift on Android workgroup,
321
00:19:03,600 --> 00:19:07,600
which is, is it yet an official?
322
00:19:07,600 --> 00:19:09,600
I know originally it started as a community workgroup.
323
00:19:09,600 --> 00:19:12,600
Is it now an official Swift workgroup?
324
00:19:12,600 --> 00:19:14,600
Yeah, yeah, it is.
325
00:19:14,600 --> 00:19:16,600
And I should sort of rewind and say that, like,
326
00:19:16,600 --> 00:19:20,600
we at Skip did not invent this idea of Swift on Android.
327
00:19:20,600 --> 00:19:23,600
People have actually been working on it for over 10 years.
328
00:19:23,600 --> 00:19:26,600
Ever since Swift came out, people have been thinking,
329
00:19:26,600 --> 00:19:27,600
"Oh, you know, you can kind of tinker
330
00:19:27,600 --> 00:19:29,600
with the Android native development toolkits."
331
00:19:29,600 --> 00:19:33,600
You know, LLVM and things like that.
332
00:19:33,600 --> 00:19:35,600
And you can get Swift running on it.
333
00:19:35,600 --> 00:19:40,600
So it's been kind of evolving with disparate groups of people
334
00:19:40,600 --> 00:19:43,600
with different, you know, needs and levels of hobbyists
335
00:19:43,600 --> 00:19:45,600
versus professional needs.
336
00:19:45,600 --> 00:19:49,600
And it's been progressively evolving,
337
00:19:49,600 --> 00:19:52,600
but it never really came together in a cohesive whole
338
00:19:52,600 --> 00:19:56,600
where everyone was sharing ideas and implementation efforts.
339
00:19:56,600 --> 00:20:00,600
And that's something that we started back in February
340
00:20:00,600 --> 00:20:03,600
with what we called the community workgroup.
341
00:20:03,600 --> 00:20:05,600
And that was a bunch of us,
342
00:20:05,600 --> 00:20:08,600
Ioannis Andri from Reedle,
343
00:20:08,600 --> 00:20:11,600
who's been deploying Swift on Android
344
00:20:11,600 --> 00:20:14,600
with the popular Reedle Spark mail application
345
00:20:14,600 --> 00:20:16,600
for quite a long time.
346
00:20:16,600 --> 00:20:19,600
He's one of the people that really has done a lot of work
347
00:20:19,600 --> 00:20:22,600
on getting the Android SDK working.
348
00:20:22,600 --> 00:20:25,600
Ifina Golfin, who has been just devoted, you know,
349
00:20:25,600 --> 00:20:26,600
to it for a long time.
350
00:20:26,600 --> 00:20:29,600
So this sort of group has all come together and decided,
351
00:20:29,600 --> 00:20:32,600
"Okay, we're just going to, you know, pool our resources
352
00:20:32,600 --> 00:20:34,600
and we're going to focus on this."
353
00:20:34,600 --> 00:20:36,600
Oh, and of course, Salim from the browser company there,
354
00:20:36,600 --> 00:20:38,600
they're also working on this.
355
00:20:38,600 --> 00:20:40,600
And so we formed the community workgroup
356
00:20:40,600 --> 00:20:42,600
and then, you know, pretty quickly proposed
357
00:20:42,600 --> 00:20:44,600
that it be made official,
358
00:20:44,600 --> 00:20:47,600
which it was a couple of months ago in June 25th.
359
00:20:47,600 --> 00:20:50,600
So almost exactly two months ago,
360
00:20:50,600 --> 00:20:52,600
it became an official workgroup.
361
00:20:52,600 --> 00:20:55,600
And the goal there is, you know,
362
00:20:55,600 --> 00:20:57,600
the goal there is not as ambitious
363
00:20:57,600 --> 00:20:59,600
as any of our individual projects,
364
00:20:59,600 --> 00:21:01,600
which are using Swift on Android, you know,
365
00:21:01,600 --> 00:21:03,600
for our own, you know, individual needs.
366
00:21:03,600 --> 00:21:06,600
Skip, obviously, to enable people to build applications
367
00:21:06,600 --> 00:21:08,600
for both platforms, but other people just to include
368
00:21:08,600 --> 00:21:11,600
in their own individual applications.
369
00:21:11,600 --> 00:21:15,600
It's really more to get an official Android SDK
370
00:21:15,600 --> 00:21:18,600
kind of published alongside these other cross-compilation SDKs,
371
00:21:18,600 --> 00:21:21,600
like the MUSEOL and the WASM SDKs,
372
00:21:21,600 --> 00:21:25,600
and establish it as an officially supported platform
373
00:21:25,600 --> 00:21:26,600
for Android.
374
00:21:26,600 --> 00:21:27,600
That's great.
375
00:21:27,600 --> 00:21:29,600
Yeah, is there, like, in the workgroup,
376
00:21:29,600 --> 00:21:32,600
is there anything in particular you have on your sort of to-do list
377
00:21:32,600 --> 00:21:35,600
that you feel like you need to tackle?
378
00:21:35,600 --> 00:21:38,600
Any specifics there that you can share,
379
00:21:38,600 --> 00:21:40,600
that you want to share?
380
00:21:40,600 --> 00:21:43,600
Yeah, yeah. I mean, so there's a lot.
381
00:21:43,600 --> 00:21:45,600
So, you know, the first sort of deliverable
382
00:21:45,600 --> 00:21:47,600
that we're on the verge of getting out there
383
00:21:47,600 --> 00:21:51,600
is an official SDK, where you can, you know,
384
00:21:51,600 --> 00:21:54,600
just like you can cross-compile from macOS to static Linux,
385
00:21:54,600 --> 00:21:57,600
you'll be able to cross-compile to Android.
386
00:21:57,600 --> 00:21:59,600
But that's really only a single piece
387
00:21:59,600 --> 00:22:01,600
of the whole Android story, right?
388
00:22:01,600 --> 00:22:02,600
What do you get out of that?
389
00:22:02,600 --> 00:22:04,600
You can get an executable Hello World application
390
00:22:04,600 --> 00:22:07,600
that you can just, you know, run on Android,
391
00:22:07,600 --> 00:22:09,600
or you can, you know, create a shared object file,
392
00:22:09,600 --> 00:22:12,600
which you can then embed in your Android application
393
00:22:12,600 --> 00:22:14,600
and then access.
394
00:22:14,600 --> 00:22:17,600
But filling in the rest of the story
395
00:22:17,600 --> 00:22:20,600
is a pretty large, you know, sort of next step.
396
00:22:20,600 --> 00:22:22,600
For example, how do you handle resources on Android?
397
00:22:22,600 --> 00:22:26,600
You know, it's different than resources on Darwin.
398
00:22:26,600 --> 00:22:27,600
How do you handle bridging?
399
00:22:27,600 --> 00:22:30,600
You know, the reality, you know, of Android
400
00:22:30,600 --> 00:22:32,600
is that it is a Java-based platform.
401
00:22:32,600 --> 00:22:35,600
You know, almost all the APIs that you need
402
00:22:35,600 --> 00:22:37,600
to talk to the system, to the device sensors,
403
00:22:37,600 --> 00:22:40,600
you know, to Bluetooth, to GPS,
404
00:22:40,600 --> 00:22:42,600
are implemented in Java.
405
00:22:42,600 --> 00:22:45,600
So you can't just do that with C bridging.
406
00:22:45,600 --> 00:22:49,600
You need to bridge across to Java and Kotlin,
407
00:22:49,600 --> 00:22:52,600
which is, you know, a pretty complex topic,
408
00:22:52,600 --> 00:22:53,600
you know, to begin with,
409
00:22:53,600 --> 00:22:55,600
and then on top of it, doing it efficiently,
410
00:22:55,600 --> 00:22:57,600
you know, for a mobile application
411
00:22:57,600 --> 00:22:59,600
is an additional complexity.
412
00:22:59,600 --> 00:23:02,600
So we've actually been working with the Swift Java team,
413
00:23:02,600 --> 00:23:05,600
mostly Conrad, on starting to come up
414
00:23:05,600 --> 00:23:09,600
with some baseline interoperability standards
415
00:23:09,600 --> 00:23:12,600
and recommendations for how Java is going to integrate
416
00:23:12,600 --> 00:23:16,600
with Android, along with the other deployment scenarios
417
00:23:16,600 --> 00:23:17,600
for Swift Java, which is, you know,
418
00:23:17,600 --> 00:23:21,600
largely server-side integration.
419
00:23:21,600 --> 00:23:23,600
So that's a really big one.
420
00:23:23,600 --> 00:23:27,600
And then just the whole story around, you know,
421
00:23:27,600 --> 00:23:32,600
packaging, ID integration, debugging.
422
00:23:32,600 --> 00:23:35,600
There's a whole world of kind of next steps
423
00:23:35,600 --> 00:23:38,600
in order to complete the project.
424
00:23:38,600 --> 00:23:41,600
Now, we sort of at Skip have our own solutions
425
00:23:41,600 --> 00:23:42,600
for a lot of these things.
426
00:23:42,600 --> 00:23:44,600
You know, we integrate with Xcode.
427
00:23:44,600 --> 00:23:47,600
We handle bundling in our own way and things like that.
428
00:23:47,600 --> 00:23:50,600
But the more that we can get that, you know,
429
00:23:50,600 --> 00:23:53,600
worked out in a standardized way
430
00:23:53,600 --> 00:23:55,600
where everyone who's using Swift on Android
431
00:23:55,600 --> 00:23:57,600
will kind of do it in the same way,
432
00:23:57,600 --> 00:24:00,600
really only helps, you know, all of the community
433
00:24:00,600 --> 00:24:04,600
in order to have, you know, the right way to do this.
434
00:24:04,600 --> 00:24:07,600
- And how has feedback from the community
435
00:24:07,600 --> 00:24:09,600
been to the work group?
436
00:24:09,600 --> 00:24:12,600
- Great. You know, people are really excited.
437
00:24:12,600 --> 00:24:14,600
There is a lot of, you know, sort of
438
00:24:14,600 --> 00:24:17,600
what next kind of questions, because, you know,
439
00:24:17,600 --> 00:24:20,600
as I mentioned, the output of the current SDK
440
00:24:20,600 --> 00:24:24,600
is here's your shared object file, you know,
441
00:24:24,600 --> 00:24:25,600
you know, go at it.
442
00:24:25,600 --> 00:24:26,600
And then people are like, well, how am I supposed
443
00:24:26,600 --> 00:24:30,600
to talk to this from my Android app and things like that?
444
00:24:30,600 --> 00:24:32,600
But it also has, I mean, there have been
445
00:24:32,600 --> 00:24:35,600
a tremendous response to the announcement.
446
00:24:35,600 --> 00:24:38,600
It's been a lot of people have joined in the, you know,
447
00:24:38,600 --> 00:24:41,600
the work group meetings with feedback
448
00:24:41,600 --> 00:24:43,600
on what they want to use it for,
449
00:24:43,600 --> 00:24:45,600
what they are currently using it for.
450
00:24:45,600 --> 00:24:46,600
A lot of people we had never heard of
451
00:24:46,600 --> 00:24:49,600
who have been sort of using it in their applications
452
00:24:49,600 --> 00:24:51,600
in various ways have cropped up
453
00:24:51,600 --> 00:24:54,600
and had really good suggestions and contributions.
454
00:24:54,600 --> 00:24:57,600
- So your work group meetings are open to the public, are they?
455
00:24:57,600 --> 00:24:58,600
- Yep, yep. They're open.
456
00:24:58,600 --> 00:25:01,600
If you look at the, you know, Swift work group charter,
457
00:25:01,600 --> 00:25:03,600
we have the schedule there
458
00:25:03,600 --> 00:25:06,600
and people can just, you know, drop in
459
00:25:06,600 --> 00:25:09,600
and, you know, ask questions or offer contributions.
460
00:25:09,600 --> 00:25:12,600
It's been a really good process so far.
461
00:25:12,600 --> 00:25:14,600
- That's great. How often do you meet?
462
00:25:14,600 --> 00:25:15,600
- We meet every two weeks.
463
00:25:15,600 --> 00:25:19,600
- So quite a good cadence to see new stuff happening
464
00:25:19,600 --> 00:25:22,600
in the Swift on Android ecosystem.
465
00:25:22,600 --> 00:25:24,600
- Yeah, actually we have another meeting tomorrow.
466
00:25:24,600 --> 00:25:27,600
- I keep going back in my head to my earlier question
467
00:25:27,600 --> 00:25:31,600
how Swift on Android is sort of different from Linux.
468
00:25:31,600 --> 00:25:34,600
And as you talk and keep talking about then Java stuff,
469
00:25:34,600 --> 00:25:39,600
it feels like it's almost like this isn't the right,
470
00:25:39,600 --> 00:25:44,600
it's like on the Apple side, this was Swift for iOS, right?
471
00:25:44,600 --> 00:25:47,600
Because you immediately associate with Android
472
00:25:47,600 --> 00:25:49,600
and Android app is a mobile app, right?
473
00:25:49,600 --> 00:25:52,600
It's not the Linux kind binary.
474
00:25:52,600 --> 00:25:55,600
As you said, the shared object file doesn't give you anything.
475
00:25:55,600 --> 00:26:00,600
It's like if on iOS you had a,
476
00:26:00,600 --> 00:26:02,600
I mean, there is no terminal, but you know,
477
00:26:02,600 --> 00:26:04,600
like had a little binary that ran without any UI.
478
00:26:04,600 --> 00:26:08,600
That is not an app in the sense that is useful for the platform.
479
00:26:08,600 --> 00:26:13,600
So it's kind of makes it obvious what a big task it is
480
00:26:13,600 --> 00:26:18,600
to have not just the plumbing to get the code on there,
481
00:26:18,600 --> 00:26:22,600
but there's all the user facing stuff that needs to be there
482
00:26:22,600 --> 00:26:25,600
and that needs to happen. That's super interesting.
483
00:26:25,600 --> 00:26:26,600
- Yeah, yeah, definitely.
484
00:26:26,600 --> 00:26:29,600
Like, you know, sort of on Linux, you can imagine,
485
00:26:29,600 --> 00:26:32,600
I know there's a project to have bindings to GTK,
486
00:26:32,600 --> 00:26:36,600
one of the popular Linux graphical toolkits.
487
00:26:36,600 --> 00:26:40,600
And, you know, with that, you can just build an executable,
488
00:26:40,600 --> 00:26:42,600
you know, and link it to those bindings
489
00:26:42,600 --> 00:26:44,600
and then you can have an application come up on the screen.
490
00:26:44,600 --> 00:26:46,600
You know, it's all in C.
491
00:26:46,600 --> 00:26:49,600
And so you're going to be able to kind of access the world that way.
492
00:26:49,600 --> 00:26:54,600
But Android applications are sort of the mirror of iOS applications.
493
00:26:54,600 --> 00:26:56,600
They're packaged in a very specific way.
494
00:26:56,600 --> 00:26:58,600
They're launched in a very specific way.
495
00:26:58,600 --> 00:27:00,600
It's not just an executable.
496
00:27:00,600 --> 00:27:03,600
It's a whole, you know, there's resources that are bundled
497
00:27:03,600 --> 00:27:05,600
with certain conventions.
498
00:27:05,600 --> 00:27:09,600
There are, you know, derived resources like translation files
499
00:27:09,600 --> 00:27:10,600
and things like that.
500
00:27:10,600 --> 00:27:12,600
So it's really more of an application environment
501
00:27:12,600 --> 00:27:16,600
that you need to think about how you're going to integrate with.
502
00:27:16,600 --> 00:27:19,600
And that's where it really gets tricky.
503
00:27:19,600 --> 00:27:22,600
And to do it in a way where it doesn't feel like
504
00:27:22,600 --> 00:27:27,600
you're force fitting some alien technology into, you know, into Android.
505
00:27:27,600 --> 00:27:31,600
And that's why, you know, it's all done using the fairly standard,
506
00:27:31,600 --> 00:27:35,600
you know, Android native development toolkit mechanism
507
00:27:35,600 --> 00:27:39,600
that's used by any application that uses any native code,
508
00:27:39,600 --> 00:27:42,600
which is, you know, largely games, but, you know,
509
00:27:42,600 --> 00:27:46,600
many, many applications have some requirement for native code
510
00:27:46,600 --> 00:27:50,600
because it's just faster and you can avoid the, you know,
511
00:27:50,600 --> 00:27:53,600
garbage collection hangs and things like that.
512
00:27:53,600 --> 00:27:55,600
Yeah, I mean, the whole thing, it's like, despite next year
513
00:27:55,600 --> 00:27:58,600
being the year of Linux on the desktop,
514
00:27:58,600 --> 00:28:02,600
the command line is sort of a very default user interface for Linux apps.
515
00:28:02,600 --> 00:28:06,600
So having just that, which is what Swift gives you by default,
516
00:28:06,600 --> 00:28:09,600
you know, server-side Swift, that's all of it.
517
00:28:09,600 --> 00:28:12,600
That's a huge ecosystem on Linux, right?
518
00:28:12,600 --> 00:28:14,600
And, you know, the bindings you mentioned, there's not even,
519
00:28:14,600 --> 00:28:19,600
you even have to, there is no default UI binding for Linux, right?
520
00:28:19,600 --> 00:28:21,600
There's GTK, there's QT.
521
00:28:21,600 --> 00:28:25,600
I'm not sure what the sort of, in quotes, market share is for either.
522
00:28:25,600 --> 00:28:28,600
And there's more than those two.
523
00:28:28,600 --> 00:28:34,600
It's on Android as on iOS and Mac OS, the story is different, right?
524
00:28:34,600 --> 00:28:36,600
There is a default user interface that everyone thinks of
525
00:28:36,600 --> 00:28:39,600
if you talk about an app on those platforms.
526
00:28:39,600 --> 00:28:43,600
And I find it fascinating how they have different aspects there.
527
00:28:43,600 --> 00:28:45,600
Yeah, yeah, absolutely.
528
00:28:45,600 --> 00:28:48,600
And so, you know, so, you know, on Linux,
529
00:28:48,600 --> 00:28:53,600
I think Qt and GTK have more or less half and half kind of distribution,
530
00:28:53,600 --> 00:28:55,600
you know, one being the default for GNOME
531
00:28:55,600 --> 00:28:58,600
and one being the default for KDE.
532
00:28:58,600 --> 00:29:02,600
But you have the benefit of it can just be a self-contained binary.
533
00:29:02,600 --> 00:29:05,600
And as you say, command line tools are also, you know,
534
00:29:05,600 --> 00:29:09,600
probably the majority of Linux applications that you wind up running.
535
00:29:09,600 --> 00:29:13,600
And so you kind of, Swift has a very natural fit there
536
00:29:13,600 --> 00:29:16,600
because you can just sort of pull in all these packages.
537
00:29:16,600 --> 00:29:20,600
And your user interface is the Swift, you know, argument parser, really.
538
00:29:20,600 --> 00:29:21,600
Great.
539
00:29:21,600 --> 00:29:25,600
Well, we should probably move on to some package picks for the week.
540
00:29:25,600 --> 00:29:29,600
We asked Mark to bring along a couple of picks.
541
00:29:29,600 --> 00:29:35,600
And my only question is, is your first pick Android compatible?
542
00:29:35,600 --> 00:29:37,600
Yes.
543
00:29:37,600 --> 00:29:44,600
So, yeah, my first pick is it's Uncertain by Matt Thompson,
544
00:29:44,600 --> 00:29:47,600
@ttt.
545
00:29:47,600 --> 00:29:51,600
And it's a Swift implementation of an old Microsoft library,
546
00:29:51,600 --> 00:29:55,600
not old, but a Microsoft paper from around 10 years ago.
547
00:29:55,600 --> 00:29:57,600
I saw this package, yeah.
548
00:29:57,600 --> 00:29:58,600
Oh, yeah.
549
00:29:58,600 --> 00:30:03,600
So it's about sort of rigorously treating uncertainty in a data type.
550
00:30:03,600 --> 00:30:08,600
It's just uncertain, you know, generic across T.
551
00:30:08,600 --> 00:30:11,600
And it's really neat.
552
00:30:11,600 --> 00:30:15,600
It lets you, rather than, you know, in your own code,
553
00:30:15,600 --> 00:30:18,600
when you're saying, "Oh, is this GPS coordinate, like, close enough?
554
00:30:18,600 --> 00:30:20,600
Is it within or without?
555
00:30:20,600 --> 00:30:22,600
I'll just pick 10 yards or something like that,"
556
00:30:22,600 --> 00:30:25,600
and then go with it and then iterate down the road,
557
00:30:25,600 --> 00:30:30,600
it allows you sort of to encode the concept of uncertainty into your data type.
558
00:30:30,600 --> 00:30:34,600
And so you can kind of treat it in a rigorous way
559
00:30:34,600 --> 00:30:38,600
and you can compose it with other uncertain variables.
560
00:30:38,600 --> 00:30:40,600
It's a really neat idea.
561
00:30:40,600 --> 00:30:42,600
Yes, it does build on Android.
562
00:30:42,600 --> 00:30:44,600
Yes, I saw it fly past.
563
00:30:44,600 --> 00:30:47,600
It was a few weeks since it's been released, I think.
564
00:30:47,600 --> 00:30:50,600
It looks like--oh, yeah, it looks like it's been in development for a month.
565
00:30:50,600 --> 00:30:54,600
So I think it was a couple of weeks since I saw it fly past,
566
00:30:54,600 --> 00:30:56,600
and it did catch my eye.
567
00:30:56,600 --> 00:31:00,600
It's kind of a--it's slightly fun, but also--
568
00:31:00,600 --> 00:31:03,600
it's not a frivolous package, but it is a slightly fun package.
569
00:31:03,600 --> 00:31:05,600
Yeah, no, absolutely.
570
00:31:05,600 --> 00:31:09,600
And he has a great little Mac application that you can run
571
00:31:09,600 --> 00:31:11,600
that uses Swift charts
572
00:31:11,600 --> 00:31:17,600
and visualize various uncertainty algorithms
573
00:31:17,600 --> 00:31:21,600
and parameters to it, which is pretty neat.
574
00:31:21,600 --> 00:31:23,600
Oh, that's great. I hadn't seen that.
575
00:31:23,600 --> 00:31:26,600
I had seen the package, but I hadn't seen the companion.
576
00:31:26,600 --> 00:31:28,600
I need to check that out again.
577
00:31:28,600 --> 00:31:31,600
That's a great package suggestion.
578
00:31:31,600 --> 00:31:37,600
I will go next with my first package pick for this episode.
579
00:31:37,600 --> 00:31:44,600
And it's Swift Complexity by Fumiyaka Tanaka.
580
00:31:44,600 --> 00:31:51,600
And this is a brand-new tool rather than a code library
581
00:31:51,600 --> 00:31:57,600
for testing a couple of metrics against your Swift source code.
582
00:31:57,600 --> 00:32:01,600
So it tests for cyclomatic complexity in functions
583
00:32:01,600 --> 00:32:04,600
and cognitive complexity in functions,
584
00:32:04,600 --> 00:32:08,600
which if you've--I haven't seen this done for Swift before,
585
00:32:08,600 --> 00:32:09,600
although it may have been done.
586
00:32:09,600 --> 00:32:11,600
I just may not have come across it.
587
00:32:11,600 --> 00:32:14,600
But I certainly have seen it in both the JavaScript ecosystem
588
00:32:14,600 --> 00:32:17,600
and the Ruby ecosystem.
589
00:32:17,600 --> 00:32:24,600
So cyclomatic complexity is a measure of how many paths
590
00:32:24,600 --> 00:32:25,600
through a function there are.
591
00:32:25,600 --> 00:32:27,600
So if your function is lots of if statements,
592
00:32:27,600 --> 00:32:32,600
you're going to have a very high cyclomatic complexity.
593
00:32:32,600 --> 00:32:35,600
And there's also a measure here of cognitive complexity,
594
00:32:35,600 --> 00:32:38,600
which is not something I've come across before,
595
00:32:38,600 --> 00:32:40,600
but apparently it measures how difficult it is
596
00:32:40,600 --> 00:32:43,600
for humans to understand code.
597
00:32:43,600 --> 00:32:48,600
And this is a tool that will give you a representation
598
00:32:48,600 --> 00:32:54,600
of high cyclomatic and cognitive complexity
599
00:32:54,600 --> 00:32:57,600
in functions that you've written in your code.
600
00:32:57,600 --> 00:33:01,600
So you can run it as a tool against the single Swift file
601
00:33:01,600 --> 00:33:05,600
or an entire project if you would like.
602
00:33:05,600 --> 00:33:11,600
I tested this, and as is any tool that takes source code,
603
00:33:11,600 --> 00:33:14,600
I always point it at the Swift package index source.
604
00:33:14,600 --> 00:33:19,600
And I don't think it's designed for projects of that size
605
00:33:19,600 --> 00:33:24,600
because it didn't manage to process the entirety
606
00:33:24,600 --> 00:33:27,600
of the package index server source.
607
00:33:27,600 --> 00:33:30,600
It gave up after about 10 minutes.
608
00:33:30,600 --> 00:33:32,600
Also, you've got to think about how you'd actually
609
00:33:32,600 --> 00:33:35,600
use the results of this.
610
00:33:35,600 --> 00:33:38,600
You probably don't want to know about every single
611
00:33:38,600 --> 00:33:41,600
cyclomatic complexity issue all at once.
612
00:33:41,600 --> 00:33:44,600
And so one of the things that they do mention in the readme
613
00:33:44,600 --> 00:33:48,600
for the package is that you can integrate this into,
614
00:33:48,600 --> 00:33:51,600
for example, a CI testing scenario.
615
00:33:51,600 --> 00:33:56,600
So you could, for example, do a quick CI process
616
00:33:56,600 --> 00:33:59,600
that diffs the pull request, finds out what files have changed,
617
00:33:59,600 --> 00:34:01,600
and then runs it past each of those files individually
618
00:34:01,600 --> 00:34:04,600
and maybe gives that report or something like that.
619
00:34:04,600 --> 00:34:08,600
But I thought it was an interesting little package
620
00:34:08,600 --> 00:34:11,600
and one worth mentioning.
621
00:34:11,600 --> 00:34:14,600
Did it suggest just to break the package index down
622
00:34:14,600 --> 00:34:19,600
to smaller components like the Swift compiler does?
623
00:34:19,600 --> 00:34:22,600
No, I may still have the error message in my console here, actually.
624
00:34:22,600 --> 00:34:27,600
Instead, it told us we had illegal hardware instructions.
625
00:34:27,600 --> 00:34:30,600
Ooh, all right.
626
00:34:30,600 --> 00:34:31,600
Yeah, I can see.
627
00:34:31,600 --> 00:34:34,600
In the past, working with Java libraries,
628
00:34:34,600 --> 00:34:39,600
I've seen cyclomatic complexity analysis that would be used,
629
00:34:39,600 --> 00:34:42,600
like you said, in pull requests,
630
00:34:42,600 --> 00:34:45,600
and would compare the cyclomatic complexity
631
00:34:45,600 --> 00:34:48,600
before and after the pull request and then say,
632
00:34:48,600 --> 00:34:51,600
"Oh, this really increases it by this amount.
633
00:34:51,600 --> 00:34:53,600
Maybe that should be a red flag."
634
00:34:53,600 --> 00:34:56,600
And I don't know how this cognitive complexity analysis works,
635
00:34:56,600 --> 00:35:00,600
but that sounds like it'd be a really interesting additional application.
636
00:35:00,600 --> 00:35:03,600
It's like, "Your pull request just made this a lot more difficult to understand.
637
00:35:03,600 --> 00:35:07,600
Maybe you should consider simplifying it."
638
00:35:07,600 --> 00:35:09,600
Yeah, I'm not sure I'd ever see any of these.
639
00:35:09,600 --> 00:35:15,600
And certainly in Ruby code, where there's a tool called Rubocop,
640
00:35:15,600 --> 00:35:20,600
which will happily tell you about your cyclomatic complexity problems,
641
00:35:20,600 --> 00:35:24,600
it's the kind of thing that quite often you'd look at it and go,
642
00:35:24,600 --> 00:35:26,600
"Actually, I'm kind of okay with that code,
643
00:35:26,600 --> 00:35:29,600
but yes, here there was a problem that we need to fix."
644
00:35:29,600 --> 00:35:34,600
So it's not something that I'd expect to see be a blocker to merging a pull request,
645
00:35:34,600 --> 00:35:39,600
but as an indicator of maybe you've gone too far in this function.
646
00:35:39,600 --> 00:35:42,600
Right. My turn, I guess.
647
00:35:42,600 --> 00:35:43,600
It certainly is.
648
00:35:43,600 --> 00:35:49,600
And my pick is SQL Cipher by Micah Moore of Zetetic.
649
00:35:49,600 --> 00:35:52,600
Zetetic is the company behind SQL Cipher,
650
00:35:52,600 --> 00:35:56,600
and this is the official Swift package for the project.
651
00:35:56,600 --> 00:36:04,600
I first learned about SQL Cipher when I was working for a bank quite a number of years ago now.
652
00:36:04,600 --> 00:36:11,600
And what it does is it is a fork of SQLite, of the official SQLite database library,
653
00:36:11,600 --> 00:36:15,600
and adds 256-bit AES encryption of database files.
654
00:36:15,600 --> 00:36:23,600
And then it obviously is immediately obvious why banks might be interested in that in particular,
655
00:36:23,600 --> 00:36:30,600
because they have strong requirements on data security, like on-device encryption, all that sort of stuff.
656
00:36:30,600 --> 00:36:39,600
And so this is what this gives you effectively, a SQLite store that is encrypted and has the normal SQLite APIs,
657
00:36:39,600 --> 00:36:45,600
so you can use it with all your normal processes, your APIs and packages and stuff,
658
00:36:45,600 --> 00:36:51,600
and this is sort of taking care of making sure that the file at rest is encrypted.
659
00:36:51,600 --> 00:36:56,600
I'm not sure to what extent it is encrypted in memory.
660
00:36:56,600 --> 00:36:58,600
It's quite extensive.
661
00:36:58,600 --> 00:37:03,600
There's a good documentation about what they actually do, how far this goes.
662
00:37:03,600 --> 00:37:07,600
Obviously, you need to consider how you handle your passphrases,
663
00:37:07,600 --> 00:37:13,600
because if you have a binary that encrypts the file, but then you have the passphrase sort of in your binary,
664
00:37:13,600 --> 00:37:15,600
that's not super secure, right?
665
00:37:15,600 --> 00:37:22,600
That is, I think we talked about this in the past with a package recommendation to deal with secrets in your code.
666
00:37:22,600 --> 00:37:28,600
But, you know, it is certainly better than just leaving the file unencrypted entirely.
667
00:37:28,600 --> 00:37:36,600
So if you have those needs, that's a great package to look at to deal with that.
668
00:37:36,600 --> 00:37:44,600
And it's probably one of the standard mechanisms actually to deal with encrypted database files on iOS devices.
669
00:37:44,600 --> 00:37:45,600
Interesting.
670
00:37:45,600 --> 00:37:53,600
And bonus, according to our compatibility matrix, it is compatible on all of them.
671
00:37:53,600 --> 00:37:57,600
So that includes the Apple platforms, Linux, Wasm, and Android.
672
00:37:57,600 --> 00:37:59,600
There we go.
673
00:37:59,600 --> 00:38:02,600
So I've actually worked with them a little bit on this,
674
00:38:02,600 --> 00:38:07,600
and it's not actually compatible with anything but Darwin platforms right now,
675
00:38:07,600 --> 00:38:15,600
because they're shipping binary XC frameworks, which I think is not triggering it to fail.
676
00:38:15,600 --> 00:38:19,600
It was somewhat urgent for them to get something out the door,
677
00:38:19,600 --> 00:38:23,600
because previously they had been distributing things via CocoaPods,
678
00:38:23,600 --> 00:38:31,600
and with CocoaPods sort of imminent, CocoaPods is really winding down.
679
00:38:31,600 --> 00:38:38,600
They needed some other way to ship SQL Cipher support for Darwin platforms.
680
00:38:38,600 --> 00:38:45,600
But I am working with them actually on getting Android support via ideally having a source build.
681
00:38:45,600 --> 00:38:52,600
I've been working actually on this for a while, both with them and with Gwendolyn Roof with the GRDB project,
682
00:38:52,600 --> 00:38:59,600
whose SQL Cipher integration also relies on the older CocoaPods binary integration.
683
00:38:59,600 --> 00:39:04,600
So hopefully we will have a better cross-platform story with that right now,
684
00:39:04,600 --> 00:39:09,600
because it really is a de facto sort of gold standard for SQLite encryption support.
685
00:39:09,600 --> 00:39:16,600
Applications like Signal use it to keep their local database of chats encrypted and things like that.
686
00:39:16,600 --> 00:39:20,600
Yeah, I just realized now that you say that.
687
00:39:20,600 --> 00:39:25,600
We do indicate that a package includes binary-only targets,
688
00:39:25,600 --> 00:39:38,600
and I suppose our compatibility check fails in the sense that all it does is fetch the binary target
689
00:39:38,600 --> 00:39:40,600
and then does nothing with it, I suppose.
690
00:39:40,600 --> 00:39:47,600
I just checked. We have no error messages, but yeah, that's a gap definitely that we have there in our checking.
691
00:39:47,600 --> 00:39:48,600
There you go.
692
00:39:48,600 --> 00:39:58,600
Yeah, fortunately on the horizon, we will potentially have support for binary frameworks for non-Darwin platforms
693
00:39:58,600 --> 00:40:03,600
in the not-too-distant future as static archives, right?
694
00:40:03,600 --> 00:40:08,600
Because there is no ABI stability for non-Darwin platforms yet.
695
00:40:08,600 --> 00:40:12,600
But even a static archive for a package like this would be sufficient.
696
00:40:12,600 --> 00:40:17,600
Even if they will only ship a binary distribution,
697
00:40:17,600 --> 00:40:23,600
there is a potential for compatibility with multiple platforms in the not-too-distant future.
698
00:40:23,600 --> 00:40:29,600
Fantastic. Do you want to give us one last package recommendation or pick, Mark?
699
00:40:29,600 --> 00:40:34,600
Yeah, I'm going to go with Lottie by Airbnb.
700
00:40:34,600 --> 00:40:43,600
That's a framework for rendering vector animations that have been exported from Adobe After Effects,
701
00:40:43,600 --> 00:40:49,600
which is kind of the industry standard for creating really fancy vector animations.
702
00:40:49,600 --> 00:40:53,600
And Lottie is a fantastic application, super efficient.
703
00:40:53,600 --> 00:40:57,600
If you ever see really cutesy kind of animation-driven applications,
704
00:40:57,600 --> 00:41:00,600
one of the notable ones being Duolingo,
705
00:41:00,600 --> 00:41:05,600
those are almost exclusively driven using Lottie exported animations.
706
00:41:05,600 --> 00:41:10,600
They're very compact, they're vector-based, so they're always sharp on whatever screen.
707
00:41:10,600 --> 00:41:14,600
They're never blurry and things like that.
708
00:41:14,600 --> 00:41:21,600
And most importantly, you don't have to worry about the creation tool because there are...
709
00:41:21,600 --> 00:41:26,600
I mean, the most famous one is After Effects to create the animations,
710
00:41:26,600 --> 00:41:30,600
but the format that it goes into, I think it's...
711
00:41:30,600 --> 00:41:32,600
What's the intermediate format?
712
00:41:32,600 --> 00:41:36,600
It's adjacent. They call it Body Move-In, the expert plugin, I think.
713
00:41:36,600 --> 00:41:38,600
That's it, yeah.
714
00:41:38,600 --> 00:41:43,600
And so the biggest part of creating animations like that is how do you actually create them?
715
00:41:43,600 --> 00:41:46,600
And so it completely sidesteps that, letting other people do it,
716
00:41:46,600 --> 00:41:49,600
which I really like about this package and this technique.
717
00:41:49,600 --> 00:41:52,600
Yeah, yeah, yeah. It's a great package.
718
00:41:52,600 --> 00:41:57,600
And you asked if the other one I mentioned built on Android.
719
00:41:57,600 --> 00:42:04,600
This actually does not build on Android because it uses...
720
00:42:04,600 --> 00:42:09,600
Sorry, my brain is...
721
00:42:09,600 --> 00:42:12,600
Core Animation for its implementation of animation,
722
00:42:12,600 --> 00:42:14,600
which of course is an Apple-only framework.
723
00:42:14,600 --> 00:42:17,600
But there is a Kotlin side to it, it's Lottie Kotlin,
724
00:42:17,600 --> 00:42:24,600
that implements them using Android's canvas vector rendering animation.
725
00:42:24,600 --> 00:42:27,600
And that's actually one of the popular packages for Skip,
726
00:42:27,600 --> 00:42:30,600
is one that bridges between these two so that you can...
727
00:42:30,600 --> 00:42:35,600
With your Skip application, you can ship a Lottie animation,
728
00:42:35,600 --> 00:42:39,600
and on iOS, it will use the Lottie iOS Core Animation package,
729
00:42:39,600 --> 00:42:43,600
and on Android, it will use their equivalent Kotlin implementation.
730
00:42:45,600 --> 00:42:47,600
Well, that's great. I have a feeling...
731
00:42:47,600 --> 00:42:52,600
I didn't stop you because I wasn't 100% sure,
732
00:42:52,600 --> 00:42:56,600
but I have a feeling we have had Lottie on the podcast before.
733
00:42:56,600 --> 00:43:00,600
Oh, okay. I did go through the past 20 or 30 and I didn't see it.
734
00:43:00,600 --> 00:43:01,600
It was ages ago.
735
00:43:01,600 --> 00:43:02,600
But I didn't exhaustively go through them all.
736
00:43:02,600 --> 00:43:05,600
Well, there are some that have been lost to time.
737
00:43:05,600 --> 00:43:08,600
Yeah, we started this as Twitter Spaces,
738
00:43:08,600 --> 00:43:10,600
back when Twitter Spaces were a thing.
739
00:43:10,600 --> 00:43:15,600
And so I think we managed to capture some of the recordings from those,
740
00:43:15,600 --> 00:43:17,600
but certainly not all of them.
741
00:43:17,600 --> 00:43:20,600
So you are absolutely forgiven.
742
00:43:20,600 --> 00:43:22,600
Plus, this is episode 61,
743
00:43:22,600 --> 00:43:26,600
and so I think it's high time that we highlighted Lottie again.
744
00:43:26,600 --> 00:43:29,600
Real-time follow-up. It was in episode 17,
745
00:43:29,600 --> 00:43:32,600
so that is in the distant past.
746
00:43:32,600 --> 00:43:34,600
It is well worth a re-mention.
747
00:43:34,600 --> 00:43:35,600
Sure. Yeah.
748
00:43:37,600 --> 00:43:40,600
Well, and with that, we shall call it another episode.
749
00:43:40,600 --> 00:43:45,600
So I'd like to thank Mark so much for your time
750
00:43:45,600 --> 00:43:49,600
coming on and talking about the Android Workgroup and Skip Tools.
751
00:43:49,600 --> 00:43:55,600
And we will be back in a few weeks with more Package Picks
752
00:43:55,600 --> 00:43:58,600
and some news from Package Index, I guess.
753
00:43:58,600 --> 00:43:59,600
Thanks for having me.
754
00:43:59,600 --> 00:44:03,600
Thanks, Mark, and see you in two weeks or next time, rather.
755
00:44:03,600 --> 00:44:04,600
Bye-bye.
756
00:44:04,600 --> 00:44:05,600
Thank you. Bye-bye.