Join Dave and Sven, the creators of the Swift Package Index open-source project, as they talk about progress on the project and discuss a new set of community package recommendations every episode.
I have a prediction for your recommendations on today's podcast.
And I know we're not talking about recommendations yet, but I want to make this prediction before we even get started.
I predict that all three of your package recommendations today will be Swift 5.9 only.
Interesting. Should I give you the answer already?
You can give me the answer. Yeah, sure. Not what they are, but the...
[BUZZER] Well, actually, let me check because I'm pretty sure that it's not 5.9 only. Oh,
it's not. No, no, I would have bet that it isn't. No, there's one that isn't.
Oh, interesting. I have the other way around. I have one that is and two that aren't. So,
between us, we have a full set of 5.9 only packages.
- Yeah, I mean, there's lots of interesting stuff
coming in, right, on 5.9, lots of macro-related packages.
- Lots of macros, yeah.
I think it proves that we did the right thing
getting 5.9 into our compatibility testing
as quickly as we could.
- Yeah, yeah, I am a bit bummed out
that we can't support or don't support
the product filter yet.
I mean, we might talk about that at least briefly now
and as part of the news, right, the plan was to support the product colon macro clause as a filter.
But we can't yet. And the reason is that products aren't declared in the, macros aren't declared in
the Swift package manifest as products. They are targets. And then they get added to a library and
the libraries, the products. So we have no way of distinguishing them at that level to support
our filters because our filters really look at the products that are declared in a package.
We have some thoughts around how to fix that. Unfortunately, the straightforward way of doing
that and supporting that is not possible right now. So bear with us. I've seen that some packages
actually have macro in their keywords. So if you search for macro, you still get them, you get a
a decent list, but it's obviously, you know, there are some, I guess there's a package
called macro that'll end up in there that has nothing to do with macros themselves.
So this is not as strong a filter and we hope we'll be able to improve it, but some authors
have worked towards being discoverable in that way. So that's actually nice.
It's also probably worth just mentioning how people can add keywords to their packages
is because it's a slightly opaque process
of we pick up keywords out of GitHub keywords.
So if you would like to add the macro keyword
to your Swift package, you need to go to GitHub,
add the keyword there,
and then we'll pick that up within a few hours.
And then once you do a search
on the right-hand side of the search results,
you can filter on keywords.
And if you then hit the macro keyword,
then you'll get everything that's tagged with a macro.
But I've been working the last couple of weeks
on something that has absolutely nothing to do
with Swift 5.9.
And it's actually something we've talked about before.
And I'm not gonna go into a huge amount of detail
because much of it is not particularly interesting,
but there are a couple of things
that I think are worth mentioning.
So just to clarify what the feature is, first of all,
I've been working on sorting out
our Google indexing problems.
So Google has, Google loves our package pages.
It sends a lot of people towards our package pages.
And I think it understands that bit of the site really well.
And then as we put documentation hosting onto the site,
Google loves us less for the documentation hosting.
And there were a couple of problems.
The first problem was we were hosting multiple versions
of each package's documentation.
And some of those package documentations are identical
because even though the package has had a new release,
the documentation may not have changed.
It may have changed, but it also may not have changed.
And so Google really hates duplicate content in the index.
And so what it saw is it saw,
okay, here's one set of documentation
and here's another set of documentation.
And I don't think there's any differences between the two.
And it actually started to punish us for that
by removing some of those pages from its index,
which is what it'll do
if it thinks you're trying to game it,
which our intentions were true,
but our actions made it look like we were trying to game it.
(laughs)
So obviously we want to have
multiple versions of documentation.
That's part of the feature that we built.
We want people to be able to go back
to previous major versions.
We want you to be able to see the difference
between the documentation on the default branch
and like the latest stable release and that kind of thing.
But so the first thing we had to do was let Google know
which version of each package's documentation is canonical.
And so every page in the documentation,
In fact, most pages on the site now have a meta tag
inside the HTML that says, if you fetch this page
and it's not the canonical version,
here is a pointer to the canonical version.
So all of our documentation pages now link
their canonical page as the latest
stable releases documentation.
So that was step one.
And the second step is then to start to tell Google
about all the different pages we have
on the documentation site.
And that is actually what I want to talk
a little bit more about and in more detail about,
because that's where it gets more interesting
that for people who are not running a package index,
which the first one is like very much a specific problem
that we just had, we've tried to fix it.
hopefully, you know, these things,
it'll take Google time to trust the site again.
And it's, we're already seeing some results, which is good.
Pages are going back into the index,
but it's a slow process.
So before we move on to going into detail
about how we're gonna tell Google
about all these documentations,
I do just want to mention that we had some contributions
on solving this canonical URL problem from Toby Herbert,
who noticed several issues with our canonical URLs,
mainly to do with kind of casing,
letter casing in some of the URLs,
because we honor the case from GitHub of like,
if you have your owner name and your repository name
with a specific case, we honor that.
And our canonicals, we're not honoring that correctly.
So in addition to some of the work that I did on that,
others like to thank Toby for all of his work on that.
That was incredibly helpful.
Most helpful actually was spotting the errors,
which is always difficult.
So yeah, the bit that I actually wanted to talk about
in a bit more detail is how we tell Google
or any search engine about all the pages
that we have hosted on our documentation site.
And we use a feature, it's actually an undocumented feature
of DocC for this.
And what I'll do is I'll link an article
in the show notes from Joe Heck,
who documented or wrote up a potential use for this flag
and also how to find and add this flag
to your documentation processing.
So the flag is emit digest.
And if you add that flag onto the end
of your documentation generation command,
you will get a few extra JSON files in the output.
And one of those files is called linkable entities.
And it's a collection of effectively
every individual piece of documentation
in the built documentation that you've just generated.
And so what we're doing is we're using that file
to pull out all of the paths
to every single documentation page
in a packages documentation.
And then we are creating a sitemap
out of that set of URLs.
So we're effectively saying,
give me all of the URLs in this documentation.
And then we'll make a sitemap that will tell Google,
look at all these different pages that we have
underneath this packages documentation URL.
And if Google then goes and fetches those,
it will get correct canonicals for all of those.
So we're hoping that the combination of those two things
is gonna be a good fix to the Google problem.
But the reason I wanted to mention this flag
is that it is something that you may want to run yourself.
So if you are creating Doxy documentation,
you might want to extract or generate this file
as part of your documentation build
so that you can have a sense of all of the different paths
in your documentation
so that you might create a manual curation
of here are the most interesting bits of this documentation
or maybe the order in which the documentation gets presented.
And again, Joe, in that article
that we're gonna link in the show notes,
he has a good bits of advice on how you can do that
in the real world.
- Right, and that's actually a massive amount of links,
isn't it?
The site map and the total number of pages
that we're effectively, or have been serving,
we just never really realized how many it is.
You had a figure, didn't you?
- We do have a figure, yeah.
When Google ingested all of these site maps,
it now tells you how many URLs it found,
not only in the kind of master site map,
but also in all of the different site maps that it found.
And it found over 250,000 URLs in the swiftpackageindex.com,
which is way more than I thought we served.
- Yeah, well, we've got 6,000 packages,
but the documentation obviously dwarfs everything, right?
That's just lots of symbols.
- It does, and I think there's actually something
that's kind of interesting in that as well in that.
So, it's actually, in fact, it's one of us,
supporters stream the company who kindly helps to sponsor the site. They have a package which,
on its own, has 50,000 or 48,000 URLs in their documentation.
Mason: Wow.
Hartmanis: And yes. So first of all, congratulations on being the biggest
documentation site by an order of magnitude on the Swift package index. That in itself is remarkable.
I think one of the things that potentially needs looking at in terms of Doxy in general
is how many pages it creates, because I can assure you there are not 48,000
useful documentation pages in that package's documentation. The vast majority of those are
are contain almost no more information
than you could get from just looking
at the function signature.
And in fact, a lot of them are because they're inherited
from like Vue or something like that,
they pick up a whole load of documentation pages
for that as well.
And I think-
- Right, right.
- That's potentially something that, you know,
it's a difficult problem to solve.
Like, do you just not generate pages
for if they don't have like proper document,
Like what even is proper documentation, right?
It's a difficult problem for DocC to solve.
But I think that potentially there is
an interesting discussion to be had around
what that balance is.
And certainly I don't think 50,000 URLs
is the right balance.
It certainly seems like the wrong side of useful.
Now there's the other side of that,
which is who should care whether we host 50,000 documentation URLs for one package? As long
as you can find the bit of documentation that actually solves your problem, it doesn't matter
that there's a whole load of unused documentation pages. So there's no kind of clear cut, like
there's a clear solution to this problem. But it is something that I would really enjoy
talking to the Doxy team about actually.
Well, it does matter a bit, right, because we are running up to certain limits in sitemap
files, aren't we?
That's true.
Yeah.
So we do need to think about chunking stuff and it sort of gets a bit more complicated
downstream or, you know, at our end and putting it all together because, you know, it's not
just a single package.
It's like we have, I believe, 400 documented packages now.
And obviously, you know, that they all come together in the sitemap.
Now we can treat them individually as package pages,
but this is a place where they all come together
and we need to funnel them through one site map.
And that creates certain challenges,
just like it created challenges
with the size of the doc sets early on
that we needed to solve.
- So the limit that Sven is talking about there
is that site maps themselves have a 50,000 URL limit.
So if you have one sitemap,
and we are now doing one sitemap per package,
if you hit that 50,000 URL limit, then Google,
actually, I'm not quite sure what it does.
Does it just stop reading at 50,000,
or does it invalidate the entire file?
That's a good question that I don't know the answer to.
But what we should probably do there,
and you know, Srinivas talked about this the other day,
but since then I've thought about it a little bit more.
I think that we should potentially,
rather than go into the rather complex solution
of having multiple sitemaps for a single package,
which we're not actually quite there yet
because the biggest package we have
does only have 48,000 URLs in it.
But I wonder if we just clip the sitemap at 50,000
because a sitemap is a guide to Google
to Google and what it you can tell Google about all your pages with a
sitemap but from each of those pages it should go and crawl from there so it's
not like if those pages are not in the sitemap they'll never get crawled
they're less likely to get crawled and less likely to get crawled more often
but if we're at 50,000 per package I think we may we may cut our losses at
that point. Well it would be nice if there was a way of ordering them right I
I mean, if Doc C had a means of putting the ones at front
at the front that actually have, you know
user contributed documentation, because I suspect lots
of them just have the default pages perhaps, right?
Because no one has documented 50,000 symbols.
So if there was a way to put that to the top
then that would solve the problem really.
- It really would.
And at that point we could potentially even say,
well, actually the maximum that we'll have is
let's say 10,000 or something like that.
But there are lots of different ways to solve this problem,
but I thought it was an interesting point of discussion,
first of all.
And secondly, that people may not know
about this emit digest flag at all,
because it is an undocumented flag.
- Yeah.
Nice.
Well, the other thing we can briefly talk about, I suppose,
is the big thing that happened last week, right?
VisionOS was released, like the SDK was released.
And that happened a bit sooner than I thought.
- Are you saying that the release of VisionOS
is more important than my site map?
(both laughing)
- Well, you know, it's funny, I'm interested in this,
but I haven't actually watched a single WWDC session
about VisionOS.
I've been more interested in some of the 5.9,
macro stuff, tooling.
And I, I thought about this.
I've early on when iOS, you know, the SDK came out, I dabbled a bit with it, but
I've always been, I've always been interested in writing apps and creating
that.
And I've done a bit of that, but I always ended up drifting towards tooling.
And I think, I think this time around, I've, I've sort of, I'm leaning in because
it seems like, you know, it's the gold rush again, or I suspect it will be to a
When this becomes really mainstream, I mean, the $3,500 device won't be the thing that starts this, you know, bringing AR apps into the mainstream, but the subsequent devices will.
So at some point, I suspect we'll have another gold rush where people come up with cool app ideas and put them out.
But I feel like I'm going to be the one that sells the shovels, not the one that's going after the nuggets.
(laughing)
And I think with the index, we're in a good position
and we actually have started shoveling a bit, right?
We have rushed to start supporting VisionOS
on top of the 5.9 that we've just added.
I mean, we weren't completely caught by surprise,
but it came earlier than I thought.
I thought when they said later this month,
I really thought, well, it's going to be this week
that it's going to drop.
but it happened just one week after WWDC.
So yeah, do you have any plans?
Are you curious about VisionOS and building apps?
- Yeah, I'm tremendously excited about the platform.
I think it's the kind of thing that watching people explore,
I also haven't actually written a line
of VisionOS code yet,
but watching people experiment and bring their apps
into the environment and kind of start to build them
with that SDK, but actually just thinking more about
now that we have a road that we're kind of,
we've got a wheel on the road
towards what AR could potentially become one day.
And I am quite excited about what AR
could potentially become one day,
and this is the start of that path.
And so while I haven't written anything yet
and I don't have any plans for a VisionOS app,
I am quite excited about it.
- Yeah, well, it's certainly, I mean,
the samples look nice.
I think I came out of WWC a bit unconvinced
regarding the use cases.
I mean, we had the discussion beforehand
and I recall saying, I'm really curious
what Apple are going to present as the use cases.
And I don't think that has truly happened yet, perhaps.
Who knows?
I mean, there's still time.
There's certainly going to be a, another sort of introduction once it actually
ships.
So maybe that will change.
But, um, I, I haven't seen any super, super obvious app, you know, that, that
would make you jump up and say, right, this, I need this, this, this is a thing
that's, that's totally different from, from all other apps.
Have you seen anything like that?
Is there anything convincing?
I think the convincing bit is actually the fact
that it is going to run what are quite standard apps
that you might see on your iPad or your iPhone
or something like that.
And I think that the,
I think there's two exciting things going on here.
We're on a path to a potential very exciting,
very futuristic AR type device.
But I think that's a long way away still.
And then you have this potential device that could,
I think, be used quite effectively in a work context.
And I think having apps around you and having,
I think the concept of kind of screens is interesting
and having apps separated from screens is interesting.
And I don't think there's any specific app
that I'm excited about,
but I'm excited about seeing what that work environment
maybe looks like. Yeah. Yeah. I mean, I think it's, it's easier to see the useful AR app
that'll completely change how you do things once the device is like actual glasses. Right.
I mean, I think that's, for me, at least it's, it's hampered by, you know, I wouldn't, I
wouldn't walk around with that thing. I mean, even if I had one, right. You're not, you're
not... Nor should you and nor do Apple want you to. Yeah, exactly. But I think they don't
want you to because right now it's not that kind of device, right? I think if they were
able to ship like real literal glasses, that would change the story of that thing. Which
is, I think we're sort of seeing right now the prototype version of obviously way more
polished than a prototype that Apple typically don't ship, right? This is like the breakout
iPhone on a board with a screen and all the parts spread out a bit and a lot bigger than
it was in its final first 1.0 shipping shape. It almost feels like it's a change in that
they actually released this now to give everyone a glimpse of what's to come way earlier.
Yes. And I think I wrote a little bit about this in Friday's iOS Dev Weekly, but one of
things that I was convinced was just a, you know, it was a feature that was being lined
up for whatever AR device that they released was last year in iOS 16 they added an AR feature
for accessibility where if you were holding your phone up and approaching a door, it detected
the door and it warned you about the door and it told you the information about the
door whether it was push or pull or that kind of thing and that was such a
clear feature for a headset of some sort. Like nobody holds their phone up in
front of them while they're walking around. It's not practical to
really do that and so it felt like this is so clearly a feature
for a headset and yet of course the headset doesn't do that and the reason
is you shouldn't be walking around with this headset any more than you
you should be walking around with your phone in front of you.
- Yeah, it's not that kind of headset yet, right?
That changes the whole pitch, yeah.
- Yeah, I'm confident that we'll see that feature
at some point in a device that you are intended
to walk around outside with.
- Yeah, yeah, absolutely.
Right, maybe to just bring this briefly back
to what we're doing.
So, platform, VisionOS platform compatibility testing
is coming, it's coming along.
In fact, the builder tests have just all passed.
So there aren't any, we're all set up.
We just have to just,
we just need to do a little more typing
and then we're done.
- It's not just typing.
- Yeah.
There have been some difficulties adjusting our test suite
because we're once again in a state where
there is no single macOS version
on which you can run all of the Swift versions
we support which is the four latest point releases so 6, 7, 8 and 5.9. And this is just my eternal
wish that at some point we won't be forced to update the OS and Xcode versions and then have
machines that can only run you know a small set of those four. I mean ideally would be even more
than four. I just want this Linux docker thing where any Linux can run any Swift version in it.
a Docker container.
And you're not going to be happy on something else.
Yes, oh god, I want this so much.
I want this so much.
I mean, I do think we need to consider virtualization at some point because it's getting really,
really, it's tricky because it also impacts our regression test suite.
It's really hard to keep testing package versions that used to fail on 5.5.
I mean, we're not even testing for 5.5 anymore, so I've just moved them forward time and time
again, to the oldest version that we support. But at some point you lose the capability to build
those packages with the older Swift versions or the newer ones. And the test cases we were
actually testing for aren't valid anymore. And it's really hard to keep that regression test in place
in some shape or fashion. I mean, because there's still value in the test, it just happens that we
don't have a package at the right version or Swift at the right version to still test that. So
So that makes it quite difficult.
And I wish that part of it was easier for our setup
and not having to manage our machines like that
and decide which one we're pulling forward.
Then we lose capacity on other Swift versions
because the latest one can only build 5.9
- Yeah.
- And so on and so on.
And on Linux, we just never have to do anything.
It just, any Swift version, we can just run.
- Yeah.
So we're currently split back across three distinct operating system versions.
Again, we have, um,
Monterey compiling five seven or anything with Xcode 13,
um, Ventura compiling anything with Xcode 14,
which is five seven and five eight maybe.
And then we now have a Sonoma, uh,
build machine that is now running, uh, beta two with the vision, OS SDK,
which to bring us back to our original point, uh,
we hope to ship soon. Yeah, I mean, by next time recording, we'll
definitely have it. I think we'll have it next week, if not late this week. Depends
a bit on when you would want to pull the trigger to actually deploy it, but it
might happen tomorrow or the day after. So, and that will be
very exciting because we'll then have compatibility status for all of our
packages with with 5.9 and the VisionOS SDK. Yeah, yeah, first new platform
since we added ARM testing, right, which was arguably, I mean it was a proper
platform in our matrix at some point, so interesting times. So we've done
quite a lot of talking about package index this week, so I think we should
move swiftly on to to some package recommendations. Would you like to kick
All right, I'll do that. The first package I have is called metacodable by Soumya Ranjan
Mahunt, and I hope I pronounced that correctly. This is the first of two macro packages that
I'm going to talk about, and it's a very nice package to tweak or empower codable performances.
And the best way to describe this is, imagine you have a codable struct and you have a field
And you've given it a nice name in Swift, but the codable, you know, the JSON
file has a different name and you want to change the fields name, just that one
fields name and imagine that struct has lots of fields, what you have to do is
you have to spell out all the fields in the, I think it's called codable keys,
to the protocol that you have to adopt, you know, to, to change or
override the key definitions.
And this package will give you an add-codable-path macro that you can tack on to your field just
to rename a single field without having to spell everything else out, I suppose.
Under the hood it just expands everything for you.
That's just the perfect use case for a macro, right?
Because that's a very tedious thing to do.
It reads much nicer because there's no noise.
It's really just about that one field that you're going to change.
Really nice.
It has a couple other tricks up its sleeves.
It allows nested paths.
So imagine you have a nested JSON struct and you want to pull out something that's like,
you know, drill down a couple of objects into the JSON file and then pull it up to the outer
layer, so to speak, and to assign it to a property there.
It can do that.
Also be the CodablePath.
And there's a Codable Compose attribute,
which is, it's difficult to describe.
It allows you to layer or compose different Codable types
into a common type.
So you can do a little refactoring
in case you're using object mapping onto JSON structs.
It's best to look at the documentation,
which is quite extensive, how that works.
So it's a really nice package
if you deal with these things in Codable,
and it's called Metacodable by Soumya Aranjanmahunt.
- Sounds like a package that's not so much revolutionary,
but it's just gonna save you some time, right?
- Exactly.
- So my first pack of recommendation also includes a macro.
It's both a very modern package
in that it only works with Swift 5.9,
but it's also a throwback to the Objective-C days,
because it is a macro that wraps an Objective-C function,
which is, I think, a nice little contrast between the two.
It's called AssociatedObject, and it's by,
I hope it's actually the second week in a row
that we've had a package by p-x9.
(laughing)
So we're back with another p-x9 package.
So AssociatedObject allows you to,
in a Swift extension, declare an additional property,
which is something that you can't currently do
'cause you can't declare anything that includes storage
and an extension.
And the way that it works is that it uses
the old Objective-C associated object API
to store and retrieve values out of memory.
And so then the implementation of it is really nice.
As an annotation on a property that you're adding
to whatever it is that you're extending,
you just say @associated object,
and you have to give it some memory management information
about whether it should retain it,
whether it's non-atomic, you know,
real throwback to the old objective C days.
But what it actually then does is it just lets you then,
on the next line, create a variable,
and that variable can have an initial value,
and it can do all the things that you would expect it to do.
And so it's, I don't know,
I really liked the idea of this package.
I'm not sure whether I'd put it into a project,
but I've certainly used Objective-C associated objects
many, many times, and they are very reliable.
- Right.
- So there's no reason you wouldn't,
but it also feels like you're bending the language
to something that it wasn't intended to do,
which is always kind of, ah, should you do that?
- Does it work on any type
or would it have to be a class, the extension?
- I think it has to be a class.
- Has to be a class, right.
Yeah, because it needs the Objective-C runtime
and that only, it probably adds
an Objective-C annotation, doesn't it?
- Yeah, exactly, yeah.
So, but I thought it was a curiosity and worth mentioning.
- Nice.
Right, well, I'm going to continue the theme
of macro packages.
And my second package is called Renamed by Joseph Duffy.
And this is another really nice package,
not a spectacular thing, but really neat.
It allows you to rename entities with a deprecation warning.
So effectively what it does, if you've renamed a property,
you can add this @renamed macro annotation
and spell out the old name that it had before.
And what it does then under the hood,
It creates a stub of the old property that forwards to the new one.
And the, and the stub has a deprecation annotation that tells users that still
use the old property, what new name it moved to, and, you know, none of that.
All of this is very easy to, to do manually, but if you have this, you
know, and you do a little refactoring, you don't need to sprinkle all this
extra stuff throughout, you can just add this one single thing to your property
and be done with it. And that's not just properties, that's also available for structs, classes,
enums, properties, functions, and more. So quite nice. That's called renamed by Joseph Duffy.
And not an Objective-C declaration in sight. My next package is one that we may end up using.
So it is a package called SwiftyESBuild,
and it's from the Tuist organization.
So Tuist is a package, an open source package
that will create and interact with Xcode projects.
So instead of having, like if you're building an iOS
or a Mac OS application,
and you've either got a very complex or a big team
working on a single Xcode project,
TUIST is a way that you can create an Xcode project
without actually checking an Xcode project
into your repository.
So you create the definition of an Xcode project
and then it generates one for you,
which is easier to work with in a big team
and has other advantages as well.
And one of the things that that organization has now added
is a new package called Swifty ES Build.
And it's actually part of a,
I think a pair of packages,
one that I think we will use and one that we won't use
because we don't use that technology.
So the first one is Swifty ESBuild
and the second one is Swifty Tailwind.
So ESBuild is the JavaScript build tool
that we use to generate all our front end assets,
JavaScript and CSS in the Swift package index.
And it's a tool that takes, for example,
TypeScript or SCSS or SAS files
or any of these kind of intermediate formats
that you have in front-end web world
and generates JavaScript and CSS
and minifies it and compresses it
and makes sure it's efficiently stored
and all the rest of it.
So that's ESBuild.
And the way that we currently build our front-end
is that we have two separate build processes.
We have the package build, which compiles the Swift code
and generates the vapor application.
And then we have a separate process
that runs as part of our deploy process,
which runs esbuild just in a Docker container
and generates the front end side of things.
And then the two things are combined
and we ship the application out to the servers
so it can be hosted.
What I want to play with is whether we can finally bring
those two build processes together using ESBuild.
So this is gonna be very specific to people doing web work.
I mean, I'm gonna say web work more than server-side Swift
because you could generate this for any web package.
This is not specific to vapor or server-side Swift
specifically. But it certainly is specific to web work. So maybe one slightly off to one side of
what most people will want, but it's something that I'm going to look at for the project.
Right, and this is a... I'm not sure if you've said it and I missed it. This is a build plugin,
right, that would run in the build phase or something?
You're right, I didn't say it and yes it is.
My final pick is... I'm sorry to say I'm going down that road again. It's called SwiftMath.
by Michael Griebling or Michael Griebling. I'm never sure if this person is of German heritage
and moved or is actually German. The name certainly looks German. And this is a bit
of a follow up to the package, Mars Jax Swift that I talked about, I guess at length in episode 27.
But this is a bit different, so I want to bring it up again, because this is a Swift
implementation of a LaTeX MATH renderer.
For those who may recall, the other package is actually using JavaScript's core and web
views to do the rendering, and this is based on a JavaScript LaTeX renderer.
The advantage of this one is that it's a Swift implementation, it claims to be significantly
faster than using web views. It's actually based on another package called iOS MATH, which is
in Objective-C, but this is a Swift translation of that, but the Readme specifically calls out
that package. It isn't just a straight up translation, it also has some claims to have
some bug fixes and improvements on top of it. So I think it sounds like Swift MATH is the successor
of iOS MATH. I think both support UIKit and AppKit. So, they aren't. It's called iOS MATH,
but I think it also supports macOS, the other one. But I only tried this one, and the really nice
thing is you can just stick it in a playground. So, you can use our feature, try in a playground,
which I get never tired of mentioning. But I just absolutely love it. I can throw it in there and
create a SwiftUI view and then have LaTeX expression rendered and this time it actually
doesn't pull in any extra stuff. It's all in a Swift package itself. So really nice.
And that opens up again of course the whole world of rendering all sorts of math expressions wherever
you use SwiftUI or UIKit or AppKit actually in that case. So really nice Swift math by
by Michael Gribbling, I'm going to go with the US version
of the name. (laughs)
- Well, I'm gonna say that that could potentially
be even more niche than my ES build plugin. (laughs)
- Well, here you go, you're coming here
for the niche package recommendations.
(laughs)
- The final, my final package recommendation
for this week is definitely not niche.
I think it fits in to almost, I would say,
any macOS or iOS package, sorry, application.
And it's a package called ReviewKit.
And again, it's another repeat author.
So it's by Cihat Gündüz and it's called ReviewKit.
And so there's been an API now for a long time
where you can request or offer the opportunity
for somebody using your application to fill in a review
or submit a star rating for your application
on the App Store.
And that API is quite unusual in Apple APIs
is that you can call it as many times as you would like to,
but it will only actually fire a certain number of times
within a 12 month period.
So if you call that function three times
within the first week of somebody using your application,
no matter how many times you call it in the future,
there is no, it will never display
to the person using your app.
And so a good practice way of offering
that kind of opportunity to review your application
is to present that prompt at carefully curated times.
And quite often, you know, it seems to be good practice
to say, well, when somebody has done something positive
in your application,
that's potentially a good time to ask them for a review.
So if they've just, if you write them a to-do application,
when somebody completes a to-do,
that's a, it's an opportunity that they've just done
something that they're happy with,
and they're done using your app at that point.
So they're probably gonna, the next step of,
after completing a to-do is probably to quit the application
or to move contexts to somewhere else.
So that's maybe a good opportunity
to present one of these reviews, review prompts.
And so the package allows you to record positive events
and define criteria.
So you can say, for example,
I'm looking for five positive events within the last 30 days
And it takes care of measuring those, keeping track of them.
And then if the criteria is hit, it will present
or it will attempt to present that review prompt for you.
And again, this is the kind of thing that it's,
there's no, as far as I know,
I haven't looked at the source code,
but there's nothing kind of terribly complex going on
behind the scenes, but it's the kind of thing
that you can just slot into your application
and get a better experience for the people using it.
And also for you, because these review prompts,
when presented correctly, can really make a big difference.
I've seen story after story after story of people saying,
as soon as I put this in,
the number of views just started to climb.
Like it just, people do review if you ask them to.
As long as you've made a good app, people do do it.
- Yeah, it's nice to have that taken care of, isn't it?
Really nice.
- It really is.
And talking of reviews,
So I actually had a piece of feedback this week
about the podcast, which was really nice.
And it was from somebody who was saying
that we should be a little more self-promotional
in the podcast, and I'm not gonna do this every time.
But it is just worth mentioning
that if you enjoy the podcast
or enjoy the package index, then sharing it,
liking the video, telling somebody about it,
I think more than the traditional like and subscribe,
I would much rather, if you enjoy it,
just tell somebody about it
that would really be appreciated by us
and is your opportunity to,
hopefully we're presenting this review prompt
after a positive experience.
- Yeah, let us know.
I'm curious what people think.
- Absolutely.
- Excellent.
- So until next time.
- Yeah, see you in two weeks.
- Absolutely, see you then.
- Bye-bye. - Bye-bye.