It's actually something we started to talk about on that failed recording, which is that the...
where it's come from is, as I've been working on this packages page update for Swift.org,
it's made me think a lot about how we pick and recommend and discuss packages. And there was
there was a bit in that failed recording where we talked about a package
and I ended up talking myself out of recommending it halfway through.
Well you talked yourself out of it, you immediately said you shouldn't be using it.
You didn't give yourself much of a chance to be honest.
And afterwards we were discussing the failed episode and you said it was a bit of a shame that that got lost
because it is actually an interesting thing. Like there's value in
talking about things that you wouldn't automatically... like a recommendation is a
funny thing because a recommendation it almost makes no sense because what might
fit my use case might not fit your use case and it might not fit everybody's
use case but there will be some people who find something in everything right?
So recommendations are a little odd in that way, but also there's value, I
think, in talking about things that you wouldn't necessarily use, and there's
still value in that. And it's something I've been thinking about,
like I say, over the last few weeks as I've been putting the final touches on
the packages page and that process that we're going to put in of people
suggesting packages to recommend and then having a kind of editorial
process of picking some packages to feature on Swift.org temporarily. And
that they shouldn't be pitched as like, "these are the best packages ever." It's
just, here are some packages. They may do interesting things.
They may do interesting things and not be for you. They may, you know, they may be
something that you can learn something from or get inspiration from or there's many many reasons
to look at a package. Yeah absolutely yeah yeah I agree and and you can learn something from
having a package discussed that is clearly not your use case but still it's well valuable in
knowing that's just not right for me it's too big for me it doesn't do it quite the way I would need
it it's you know it's too complex because of the yeah trade-offs it makes you know lots of things
are just trade-offs, right? There isn't the perfect package because the perfect package
is effectively almost, you know, often something you would have to write yourself because that's
the only way to guarantee it's actually tailored to your requirements. I mean...
>> Can I suggest Foundation? >> Yeah, but is that a package in the sense that, I mean,
obviously at some point it'll be a package in the... Although actually that's a great point,
because many people will argue Foundation isn't a good choice for what they're doing.
You know, they might be on resource constrained devices.
Many Linux folks say, "I don't want to pull Foundation in because it makes my binary bigger,
compile times are bigger." That sort of thing. But compile times isn't going to be an issue
if it's a library like that. But once it's a package, that'll have an effect. Although I think
on Linux, it is even part of it. Swift core foundation is binary. I'm not 100% sure.
But either way, you'll bloat your binary. You have more complexity if you pull in a dependency like
that. And in other cases, of course, you're going to import foundation because when you're building
an app, there's so much you need. You're eventually codable, all that stuff. You need foundation.
that's almost unavoidable. But it is a trade-off, you know, not every environment is the same,
not every system is the same. For some people it's a natural thing to pull in, for others it's
the last thing they want to touch. Yeah, it's a complicated subject to talk about because
you don't want to, or certainly I don't want to ever upset anyone if I talk about somebody's
open source work here and end up even implicitly saying, "Well, I wouldn't use it," then I don't
want to upset anyone. That has the potential to upset someone, but I think that discussion is
really valuable. Maybe we should just not call them recommendations because that implies some
degree of experience or testing or usage of a package that you're saying, "Well, I've used this,
and I therefore recommend it, which is certainly not what I do when we look through these packages.
I skim the packages, I look at the ones that look interesting, and then we talk about them.
Yeah, my process is a bit different, but I think that's also valuable that we don't do it the same
way, because that leads us to pick different packages for different reasons. Are you saying
you test every package you recommend? I actually do, yes. Just today, my pick today, I tried it,
it. I found a bug. I reported it. It's already been fixed. There's a new release. But I feel like,
I mean, that isn't always the case, but most of the time I pick packages that I'm really curious
about. And part of that curiosity is trying it out. And that's why I often mention that stuff
works in trying a playground because that's how I try it. That's the easiest way to try it. And
And that's a huge, that's a huge help in trying them, but today's package that
didn't work and I created a little package, which actually I realized I do in a
complicated way, so what I normally do is create a directory in terminal, the Swift
package, init, type executable, type library.
Actually today I just did an Xcode project new package.
It's so much easier.
It sets everything up that I had to fiddle around with and it's
immediately there in Xcode.
Sometimes you have these Jordan paths, you keep going down and you never reevaluate what you're actually doing.
But yes, I often do try it because I'm interested in those aspects of it.
How does it actually work? And that's later on.
That's actually a big part of what I want to highlight in that package.
How does that actually work? I was really curious about that.
And that's often the case, not always but often I want to see how it actually
works in practice. Well now you're making me feel terrible and like an amateur.
Which is exactly why I brought it up.
I'm not saying, although I did notice that halfway through your thing that you
said at the beginning you said I test all packages and then halfway through it
switched it off. And I'm not saying that I don't test any packages but it's
certainly, in fact I can give you a little preview, none of my packages that
I'm going to talk about today I haven't tested any of them. Shame on you.
Shame on me, absolutely. Well I think the ones that I don't test explicitly are
often ones I have used in the past. I'd have to check. I mean, I'm sure there's been one
or the other where I picked it for other reasons and I didn't actually run it, but...
You get a gold star then I will get one printed and send to you.
Oh, excellent. Excellent. What material is it going to be? Is it like valuable metal
or something? Is it an Apple-like trophy?
Oh, Apple-like. Yeah. Okay. We'll give you one of those little pens that Apple...
Little, there we have it. Little, little is the value of my work.
Right. But I think that's interesting though. I think that's definitely an interesting
discussion to have about what would be alternative labels for instead of recommendations, highlights.
Yeah. We've been talking about this with that pull request and the word that we've settled on there,
which I quite like is Showcase.
- Oh, right, yeah.
Yeah, it's a show, yeah, that's good.
I think that's really good
because that implies it doesn't have to be ready.
A showcase is often a prototype or a proof of concept
or just something interesting.
I think that's good, yeah.
- It can be a preview.
It can be, yeah, it's like here is a selection of things
that might be interesting.
- Yeah, no, I like that.
Yeah, I hadn't actually,
didn't remember what the final version actually was, yeah.
And we've also been talking this week about a blog post, right?
Yes, we have.
And that's a really interesting blog post that we came across.
It's called "Worrying about the NPM ecosystem."
And it's a blog post by Sam Bleckley.
It's actually quite, well, old in internet terms.
So this is three years old from June 29, 2020.
And this is really interesting for us in particular,
working on the Swift ecosystem and creating a package index on the ecosystem.
Because what Sam has done is analyze the NPM ecosystem through the lens of, of
what packages there are, you know, statistics of the package index.
And that's really interesting.
I mean, obviously there are many things that are different between NPM and
Swift, size being probably the most critical part of it.
- Well, it did strike me actually as,
it did strike me as I was reading through it again
before today's recording.
One of the, well, so first of all, actually,
I think it's really nice to see somebody step back
and look at a package ecosystem like this for the long term.
And we've got lots of history to look back on.
This is, the Swift package ecosystem is obviously something
that we're both very intimately connected with
and passionate about,
but there have been a great many package ecosystems
to learn from, NPM being one, of course,
but even back before then, CPAN
and lots and lots of package ecosystems.
And it's really nice to see somebody taking a long-term look
at like, well, what are the problems?
How is the reality of this ecosystem
compared to an expectation?
did strike me as I was rereading it that maybe we should put a limit on the
number of packages in the package ecosystem. So you know once that last
once that fifty thousandth package is in that's it we're full. Yeah some old ones
need to go. That's right yeah something it's not that that's it can never change
and I'm not really being serious about this but but there is actually there is
actually an interesting point to be at least considered of like, is there a
point where a package ecosystem, once it goes over a certain point, these problems
are unavoidable? I think so to some degree, but also there's inevitably a
layer of cruft that'll accumulate over time. I mean we see this already, right,
there are packages that are effectively unmaintained and have been unmaintained
for years and years and years.
They probably don't even compile on any, on any of the versions that we test,
you know, they stopped with Swift 4.2 or something like that.
I'm sure there are some, um, that we just ended up with and, you know, there's,
there's no process by which we would go through and drop them.
So we carry them forward probably forever.
I mean, unless we decide at some point, right, this, this isn't passing any, any
any compatibility checks never has or hasn't in the last X years.
Is that a reason to drop it?
I don't know.
Is it who's what's what's the
it's a good question that I don't really have a good answer for, but also we're in
a actually a much better position than we really should be because there was a point
I can't remember which Swift Swift version it was.
There was a point where we just had to say that anything, I think it was anything
three and below just had to go.
Like even though there was package manager support
for those, they were so old and it just didn't work anymore.
So we kind of had a reset around Swift 4, I think.
- I believe package dump failed to work
on very old packages, yes, or something like that.
And package dump really is central to how we gather
the very basic metadata for a package.
So if that fails, there's really very little to glean
from a package, yeah, that might have been the reason.
And so we had that reset and you're right
that there are definitely packages in there
that are so old that they don't compile
on any of the versions that we test with
and will probably never be updated again.
- Yeah, and what's to happen with them?
And you can imagine NPM is going to have a lot of that.
How old is NPM?
- Tens of thousands, yeah.
Oh, NPM is, I don't know, 10, 15 years old.
I mean, so in, in many regards, it's a glimpse of the future of
the Swift package ecosystem.
To some degree, I'm not sure size wise it's ever going to approach anything like it.
We should mention like in the blog post, Sam lists 1.3 million packages in the
NPM ecosystem, which is obviously more than two orders of magnitude, more than
we track right now, which is 6,000 packages and a few. I guess we're also not tracking all of them.
I mean, clearly we're not because those are just the open source ones, which is also true for NPM.
But we also are probably much less established as the source where everyone goes to register
the new packages. That's probably more true for NPM than it is for Swift package index.
So that's certainly a difference.
I mean, the size is just, I mean, imagine two orders of
magnitude, what that changes.
Um, and there are some other interesting aspects that he lists that he looked at
that I found really quite surprising.
So he looked at a, um, a thing, circular dependencies of packages, and that
is something I did not really expect.
So there are 1,700 packages that are directly dependent
on themselves.
- Yes.
- Which I can't quite grasp how that works.
- Well, he even says in his post, he says,
yeah, they depend directly on themselves,
either perfectly circularly or a different version
of the same package.
I have no explanation for that.
- So the other example I can understand
like 2,500 packages depend on themselves via two steps. And he gives an example that is quite,
well, it's still strange, but at least it makes a little more sense how it could happen.
There's Babel Core that depends on Babel register and that again depends on Babel Core.
But given that they're all related to Babel, you'd think, I mean, how would you build a dependency
tree where that can actually happen? I found that really strange. I wonder if there's something
particular about NPM that makes that possible. So we should say that the blog post is also
interesting for us because we want to do some of the same analysis for the Swift ecosystem soon.
We're not in a position right now to do it because we're not actually gathering all the
underlying information yet that we would be able to make that same analysis. But I'm really curious
that can actually happen. I think part of this is
is actually a little bit specific to JavaScript the language. We talked about
Foundation earlier and JavaScript is a very very lightweight language and
doesn't have anything like Foundation and so yeah part of the reason that are
1.3 million packages is that a hundred people have all tried to solve all the
basic problems and they've all put a package out for all the basic problems
And those packages get deeply, deeply ingrained in those dependency
graphs. And I think that's a lot of these circular references are caused at least
in part by that problem. Yeah, that's actually in one of my first notes about
what are potential lessons. I think that's really it because a lot of the
analysis that Sam is doing is, you know, highlighting his surprise at how many,
how deep the dependency trees are and how wide they are.
So how many dependencies get pulled in?
There's, there's, um, many packages that have 250 dependencies and no, actually
2,500 dependencies is the maximum.
And, and I think, uh, 2,500, 2,500.
Yes.
Yeah.
Sorry.
I was quoting from Crates, from Rust comparison.
So there's very, very, very, very deep dependency trees.
And I thought about how or why that is.
And I think you're exactly right.
That's why what I thought as well, a strong and good standard library probably
trims that tree by a lot because it literally prunes the tree of all these
packages that other ecosystems don't need.
And I think the other one is UI libraries that are practically always
OS libraries that aren't part of the Swift ecosystem per se.
Like, like we're not tracking Swift UI as a package that has sub dependencies
or anything like it, UIKit equally.
That that's all platform libraries, which NPM really doesn't have, right?
any, any web framework and there are lots of them needs to ship all this as a
dependency, right, that you then pull in and use.
I think an area where you see the same issue is web development.
And, and we are actually the, that's interesting.
The SPI server package is the package with the most dependencies and it's 56.
Uh, and that's mostly, um, the vapor and friends because that's a very rich
framework with lots of dependencies. Vapor has everything nicely broken down into individual
things. If you use a database, you by nature use the foundational Postgres library, then
I think there's even a separate one for the Neo stuff and then there's a fluent layer.
I think so I have at least three, maybe four database libraries that you pull in when you
use Postgres as the database in vapor.
And that is the case for quite a number of other packages.
I should also add in our defense, those 56 includes def dependencies.
So it's not, it's not entirely that, uh, that bad in the, in the shipping binary.
But I think we are sort of an example of a more typical NPM package in that sense.
in that a lot of stuff isn't OS library stuff.
I mean, I don't think, I'm not even sure the Postgres,
I think the Postgres stuff might need libraries.
I need to check what we actually need in our Docker image.
But a lot of the stuff we build to run is very foundational
in the sense there's very little that the OS
actually provides as underlying libraries that get used.
A lot of it is just straight up code
that is built on purpose to provide the functionality itself.
What I also found interesting,
and I'm not sure if you've followed that link,
there was a follow-up post where Sam looks
at the same analysis for Rust,
and that was quite interesting.
Did you see that one as well?
- As I skimmed that one,
but I didn't read it in full, full depth.
- Yeah, it's a bit interesting and particular for our case,
because it's sort of in between.
So Rust at the time, this was July, 2020,
had 50,000 packages. So we're just an order of magnitude away now from us.
It also includes cycles, dependency cycles, so that might indicate that it's just something
that happens. CB; This is the ghost of Christmas future.
MG; Yeah. And a lot fewer dependencies. And I think that is to our point that a strong
standard library probably prunes that tree quite a bit. And he mentioned that, Sam,
It's very likely due to a few very popular packages with few dependencies that early on
caught on and were crystallization points for all the work.
I think Swift is in a good position, especially with many of the packages in backend development
and Swift server group, SSWG packages. Swift Neo, for instance, is taking care of a lot of the
plumbing in terms of networking, where Swift benefits from having packages in lots of areas,
but not multiple different implementations. So there's typically one good library that does it,
and all the effort to maintain it is focused on that one library. And then it gets used a lot and
battle tested and sort of often they have good dependency trees in the sense that there are
few dependencies that they themselves have, or it's the same ones again and again. So I think all
of this helps a bit in keeping this growth in check. But obviously it's going to be interesting
to see if that changes and how that changes as the index ecosystem grows.
Stay Forever It will certainly be something we have to keep
an eye on. While you were just talking, I had a suspicion and I just double checked it.
So we have actually two dependency trees in SPI Server. As you say, our Swift dependency tree is
quite large because of vapor in the database dependencies that we bring in through that.
We also have a JavaScript dependency tree because we have a front-end process and that has its own
build process and we use the standard JavaScript dependency manager that we've been talking
about today. And I did pick our dependencies very carefully with the front end and I've
just double checked. We have three top level dependencies and those dependencies have
zero second level dependencies. Oh nice, I was sort of racing myself for a big number there.
No, so it's actually we're the opposite, we're living in opposite world.
Wow. We do have, so I should just mention, we do have a much bigger results file because
in production we only have three dependencies but our build environment gets into that whole messy
NPM tree. So we have some development dependencies and we have some production dependencies and our
development dependencies are much messier than our production ones. Right, right. Yeah, I need to
to check, I'm actually curious how many Swift production dependencies we actually have.
I mean, it's not going to be a lot because we have snapshot testing and that sort of
stuff, but there aren't. I can't think of a lot of specific test dependencies that we're
pulling in.
Toby
Obviously we'll put it in the show notes, but I would thoroughly recommend reading this
blog post if you have even the slightest interest in what we've been talking
about because it's fascinating. Well written, it'll make you laugh a couple of
times. It's a great blog post. Yeah, really good and I'm curious. So we'll
definitely endeavor to produce the same numbers, same statistics for Swift
Package Index. We're just not in a position to do that yet because we're
not tracking the full dependency trees but it is coming. Well I think
it's also good that we're thinking about this while the package ecosystem is this
size. Yeah. Because I think one of the ways that you stop it happening is by
showing it happen. Well the question is can you really? I mean how?
Like we were saying earlier I mean I do believe there probably is a size at
which this becomes inevitable but certainly there are things you know I
I think we're in pretty good shape to delay that inevitability at least a little bit.
Let's see how it goes.
So should we showcase some packages?
Let's showcase some packages.
You can kick us off this week.
All right, I'll kick us off.
So my first package is actually two packages in a trench coat.
And I do suspect one of them might appear.
depend on each other, right?
Actually they do, but it's
unidirectional.
I suspect they might also be in iOS Dev
Weekly later this week,
but I'm calling first dibs. And it's
from our
good friends Point Free. It's Swift
macro testing
and Swift snapshot testing.
Disclaimer, Point Free Co. are a sponsor of
the Swift Package Index,
but I just can't resist. I'll
always recommend them. They're good packages, Bront.
I saw both of these in the RSS feeds and as soon as I saw them, I just skipped over them
because I needed to pick them up. You left them for me, nice. Yeah, they're really great. What
I love about them is that they are useful, but also useful in interesting new ways. And they
really build on top of each other. So, right, let me explain what they do. So, the first one,
Swift macro testing is about macros which is a new feature in Swift 5.9 and Swift 5.9 obviously comes
with the ability to implement macros. It also has some facilities to actually test your
implementation and what it does effectively is it adds an assert macro expansion and then you can
inline, you know, have a literal string that is your expectation of what it should look like and
the macro definition itself and then it compares that the macro expands into what you wanted it to
expand to. And the Swift macro testing package expands on that, no pun intended,
by giving you more capabilities because the assert macro expansion test, while nice,
is fairly basic. So it only allows you to compare the strings and you sort of have to manage that
yourself, what this, their, uh, assert does is it actually puts the expanded
expectation into your source code in line.
So you don't need to prepare something and then copy paste it in.
You, you write an assert with the macro definition in it, as you call it.
Then you run the test.
You know, if you know how snapshot tests work, you normally run the
test and then it writes out a file.
And then you confirm, yeah, the file looks like, like, you know, as I expect.
And then when you run run it the next time and the file is there, it just compares the
next snapshot against the file.
Right.
What it does here is it, it is not file-based, but it actually places the expansion into
your source code in Xcode and it uses Swift syntax under the hood to understand your
test structure and does effectively a live live source edit of Xcode.
source edit of Xcode, so it as if you were typing out the expectation itself.
So that's quite nice because you don't need to fiddle with the expectation.
And obviously, once you've done it the first time, it'll then, if it's different,
it'll highlight a difference, right?
It only does that if there's nothing there yet.
So this is your first capture of the difference.
And it goes beyond that because it doesn't just snapshot your expansion,
it also snapshots diagnostics and fixits, which is something that the built-in
certain macro expansion doesn't do.
So this is only for testing the expansion itself
and Point Free Co's tool also allows you to test
all the edge cases, like diagnostics when there's something
wrong with your macro call or fix-its when you want to test
what your suggestions are, how to fix issues
with the macros.
So that's quite nice.
- So I think I did see the macro in the first place
macro package fly pass, but I didn't look into it in much detail yet. Like I say, I
knew you would take it. But what I did see was, I think, what you're about to talk about,
which is the other side of this, which is an enhancement to Swift snapshot testing,
which added support for inline testing this week. And even now I understand why they added
that. But that feature, even on its own, is invaluable. We use snapshot
testing in a couple of different ways. We have HTML snapshot testing, which takes
fully rendered HTML files of hundreds and hundreds of lines of HTML
and snapshots those. And those obviously suit file-based snapshot testing really
well. But then we also have a whole load of other uses of snapshot testing. Like
snapshot tests and SQL queries and we snapshot test even just a bit of like
JSON like in a fragment of JSON somewhere or even just a string like we
you know we render a date or something maybe we'll just snapshot test that and
currently all those live also on disk which is it's okay it's not terrible but
I really liked the idea of being able to have those snapshots just in line in the
in the code and and now finding out that they will automatically update if you if
if you ask them to, that's just the icing on the cake.
- Yeah, that's really nice because you always have to
sort of make the decision.
I mean, it still doesn't make sense to do an inline snapshot
for hundreds of lines of output.
That's clearly something you want to stick in a file.
- Of course.
- But many smaller ones are just really nice to have inline
because you don't need to go hunting through the file system
to actually look at the snippet, right?
It's really nice if a three-liner, four-liner
is actually inline there in the test.
And that's this amazing new feature of the inline testing.
Not only that you can have it in there,
but it actually automatically manages
that representation inline and you just,
effectively you just look at it,
yeah, looks all right, run it.
And then if it fails, it gives you the same message
as if it was a file.
And obviously also you can always see the diff
in your source tree, even if you were to save it.
That's great. It sounds like a real, um, a real, uh, enhancement to, to,
to the Snapchat testing library.
Really great couple of packages, um, and, and really nice, um, combined,
um, yeah, release of those.
So my first, um, completely untested and, and experimented with package
is, um, is, I mean, so, okay. So, so it's, the package is cloud's
cloud kit sync monitor.
So in order for me to have tested this,
I would have had to set up a CloudKit project.
And you know, there's a lot of testing in that.
It's by Grant Gruninger,
and it monitors the state
of an NS Persistent CloudKit container
synchronization process.
So I think this,
if it does what it says on the same,
which I'm sure it does,
I think this is a potential,
a package that potentially every CloudKit application should include because one
thing, one area where CloudKit is a little weak,
certainly in the operating system and in also in applications that use it,
is feedback on what's happening with CloudKit sync. Has it finished?
Is it still going on? What's happening? Did it error?
And this allows you to hook into all of the notifications sent out by the
persistent CloudKit container and translate them into some published properties
that you can then monitor in SwiftUI and update some UI
or keep whatever tabs on it you would like in an easy way
without having to subscribe
to all those different notifications.
And it doesn't come with any pre-built UI
as I believe it shouldn't.
I think that's something that you should,
each application should determine
how to surface this information if they choose to.
But it does kind of tame all those notifications
and give you a nice way to just take a look
at what's happening with your sync state.
It's got a great read me file.
It's actually been in development for a couple of years,
but I've not come across it before.
- Nice.
Yeah, I mean, that's super hard to test.
Actually, as you were saying it,
I realized I did not test the macro testing package.
So there you go.
It's immediately--
- See, I knew it wasn't.
I knew your virtue wasn't as complete as you claimed.
- But snapshot testing I have, I've tried.
- Well, we've all used snapshot testing.
- All right, we all have.
(laughing)
Right, my second pick is called Lighter by Helge Hess.
And this is a really interesting package.
It's not new, I've known about it for a while,
but there was a release in the last week
or last couple of weeks.
And this is the package I was alluding to earlier
when I said I was curious
about how it's actually implemented.
So Lighter is a very interesting SQLite database
access package.
And this is probably an area where there are quite
a few candidates in the package index
that is well serviced.
There's a rich field.
Like for instance, there's GRDB by Gwen Del Roy.
That's probably the most widely known and used representative of the package,
of a SQLite database access package.
But Lighter is really interesting in its approach and its use case, effectively.
It is a package that source generates SQLite library bindings.
And it can do that in two ways.
One is just straight up a layer that directly interfaces with the C library.
So it's dependency free what you get out of it.
And the other one is a, it generates an additional layer on top, which is a lighter
layer, so it gives you a nicer high level API to talk to your database.
But what's really interesting is the, so the marketing, if I can call it that of the
packages, it's, it's really, really fast.
And it has a performance test suite where it calls some numbers that are quite remarkable.
So in some of the tests, it's six times faster than GRDB.
And it's three times faster than GRDB if GRDB is sort of manually tweaked,
effectively by avoiding codable, which is apparently a very big price to pay there.
So it is quite fast in the tests that Helge is running. But I was really curious about some of
the things he's doing in his examples because he has an example how you filter on a query. So,
you know, as you can imagine, you run a database, get me all the records from a table and filter,
you know, like a typical where clause. But it's written like a Swift filter with a closure.
you have, for instance, I loaded up a music, there's a Chinook, I think it's called a test
SQLite database that you can download, which has sample data in it and has tracks like music tracks
in it. And you do db.tracks.filter, and then you pass in a closure where you can apply
a filter on the tracks individually, right? You do $0.length, like the track length,
And then I queried for all the tracks that are longer than 300 seconds.
And that runs, I mean, obviously with the number of tracks in it, I wasn't
able to tell if it's fast or, or anything, but I did actually check how it's
implemented and that was really interesting because what it does
effectively, it binds the, the closure as a C function pointer into, to
the, to the SQLite library.
So the library actually runs your closure directly, like as a function
in inside the database, you know?
it's as if in a Postgres database you had shipped your code as an extension and then called into it.
You had all this done ahead of time and then you were calling into it. It can actually do that with
straight up Swift code. I was really surprised that that works. I mean, obviously there's some
unsafe pointer stuff going on to make that work, but that explains how that interface works and
how the claims can be made that this works without having to translate all sorts of variants of Swift
code into where clauses, right? That's not happening. It's actually just executing the
predicate directly in C in the library. And that's remarkable. So yeah, it's a really interesting
package. I tried it out with the Chinook database works as advertised. It code generates. So there's
a build plugin that comes with it that auto generates your database access layer. You
give it an input database and it looks at the schema and pulls out all the stuff. And
that worked fine for that database. Well, it worked fine actually. That's the thing
I pointed out earlier. There was a formatting issue in the underlying database and that
broke the generated code and Helga fixed that really quick. And that's the one thing I had
in my notes when you adopt that sort of library that generates code, there's a slightly bigger
risk that things might not go 100% if the code generation doesn't work right. So yeah, you have
a bit of an extra risk there in your dependency. On the other hand, if you don't regenerate right,
what you already have is going to keep working. So at least there's some safety there, but it's
It's something to bear in mind for packages like this.
But I believe if you need a really fast
SQLite database access and you don't want to deal with
the C aspects of the SQLite database,
which is a database library,
which is probably not something you want to be doing,
this looks like a really great option.
- That's great.
And I like how in the description of the package,
it ends with dependency free.
So it says Swift APIs for SQLite,
type safe down to the schema, very, very fast
dependency free.
I think, you know, the fact that it's made it
into the description of the package is obviously,
that's how important Helga is taking it there.
Although I would argue it does have a dependency on SQLite.
- On SQLite, yeah.
(laughing)
- But I think we'll forgive him.
- Well, on Mac OS and iOS and everywhere,
the library's there.
It's probably only on Linux where you--
- So then we get into defining how do you define
the dependency?
(laughing)
- What's the dependency?
- But let's not go down that route.
- It depends.
- Instead, we'll go back to my un-researched,
un-tested list of packages.
- You really gotta have one up, won't you?
(laughing)
- Well, I was gonna say, actually this one,
I haven't tested this version of it,
but I have used this package in the past.
It is shipping in the iOS Dev jobs app,
which uses SwiftUI Introspect by David Roman.
And I have a feeling we've talked about this package
on the podcast once before right at the very beginning,
because I think I just started,
I just finished using it in the app
when we were looking for packages to talk about.
And I think I talked about it then,
but I'm gonna mention it deliberately again,
because it's just hit a 1.0 milestone.
which is always worth celebrating,
especially for a package that is so good like this.
What it does is it allows you to get at the underlying
UI kit or app kit controls underneath a SwiftUI view
in a safe way so that you can,
if there is something that the SwiftUI view
doesn't quite do, it means you don't have to completely
throw that SwiftUI view away.
You can, if it is based on a UI kit or app kit control
behind the scenes, you can get access to that,
modify whatever properties, call whatever methods
you would like to on that object.
And it does it in a safe way so that if the underlying
implementation of SwiftUI changes,
it does not crash your application,
it just doesn't set those properties.
Now of course, if you do something in that code
that you then 100% rely on later,
That's your responsibility to make sure that
if that code suddenly goes away,
your application should still at least work.
But this is a really great library
for filling in those little gaps.
And those gaps are getting less and less every year.
There will be a happy day,
and I'm sure David will agree with me
that it will be a happy day when he can say,
this library is no longer necessary.
And there will definitely come that point.
One of the things that I liked that has been added
since I used the package,
which is an opt-out by default to new versions.
So when you introspect something,
let's say you're looking for a scroll view
inside the SwiftUI scroll view,
you now have to say, I'm looking for it on iOS,
version 13, 14, 15, 16,
And then if version 17 comes out like it just did,
you would have to manually opt in.
You could say like I've tested this on the new version.
I checked it.
I'm gonna add that additional case
so that it enables my introspection on the new platform.
Yeah, I think it's a great library.
It supports, there's a huge list of controls
that it supports, everything from page controls
scroll views, to steppers, to tables, to all the different lists and grids and
things like that. It supports an enormous amount of the SwiftUI API. It's
been around for a long time. It's been around for three years now, which I think
is pretty much as long as SwiftUI has been around. Wasn't SwiftUI's first year
2019? I think so, yeah. Isn't it SwiftUI 3.0 or something?
Well, if it's 2019, wouldn't it be four? So yeah, maybe it was a few months after SwiftUI
first showed up, but it's certainly been around for the vast majority of SwiftUI's lifetime.
And I can recommend this package because I have used it.
Nice. And with that, I think we'll call it another episode, and we will be back with
and some more showcase packages next week
and more news from the Swift Package Index.
So we will speak to you in two weeks.
- See you in two weeks, bye bye.
- All right, bye bye.
[ Silence ]