All Episodes

September 30, 2024 • 23 mins

Ben Scheirman is back for part 2 of our interview on SwiftUI Migration. In this episode we focus on navigation, data handling and Swift packages.

Guest

Announcements

Links

Related Episodes

Social Media

Email
leo@brightdigit.com
GitHub - @brightdigit

Mark as Played
Transcript

Episode Transcript

Available transcripts are automatically generated. Complete accuracy is not guaranteed.
Leo Dion (host) (00:14):
Welcome Apps.
I'm your host, Leo Dion.
Today I'm joined
with Ben Scheirman Ben, thank
you so much for coming on one elephantin the room we haven't talked about, and
you kind of just briefly mentioned it?
Is your data.
You've got Like 32 choices ofhow you can have your hooked up
to Swift UI, and on top of thatyou have to work with UIKit.

(00:36):
How are you doing it?
Are you still doing observed Object?
You still using Combined?
Are you migrating to observable

Ben Scheirman (guest): So we because can't 16. (00:43):
undefined
actually fantastic
and I am looking forward toforward to being able to do that.

Leo Dion (host) (00:53):
In the year
2026

Ben Scheirman (guest): but yeah 2026 probably but (00:54):
undefined
but we gotta move forward.
So there's also the libraryby point freeze, and that is a

Leo Dion (host) (01:03):
course point
free

Ben Scheirman (guest) (01:04):
Yeah,
that is a back port Yeah free
framework that works

Leo Dion (host) (01:08):
Oh that's

Ben Scheirman (guest) (01:09):
maybe even 15.
remember what, but basically it's,it does the exact same thing.
It's, it's not rocket science.
Like you can go look at the source code.
It's, it's not tooterrible to understand.
But side, problem is thatwe currently are not yet.
on SWIFT package managers.
So we can't pull inlibraries like that just yet.

(01:29):
and stuck place where we, we, wewould like to be able to adopt
libraries like that but can't.
So with the observableobjects, I guess that the
primary reason why observable objectversus observable is that when you, I.
When you property.
So if you do that at the rootof your app and anything in that

(01:52):
changes, it triggers like areflow of all the views inside of

Leo Dion (host) (01:56):
Unless you mark it as
observed, ignored
on purpose.

Ben Scheirman (guest) (02:00):
yes yeah, but like the observation framework
just makes this a non-issue.
'cause it's just whateveryou access in the view.
So if you just own the objectchildren, you don't need to when.
when that happens, and, and you can,you can stuff in the environment
and like four layers deep, it canpull it out again, and then at that
layer it observes those are theviews that are gonna get re-render.

(02:21):
important.
But we, we object, currentlycalled a model that we use
for each one of our views.
That model is, is, I hate touse the term view model because
this is like overloaded, butlike as as know what thing is
you know, call it what you want.
I think the term modelfor if it's ex like.
it's a, it's nestedinside of our view type.

(02:43):
So it's obvious that and that letsus pull dependencies handle all
of the, any kind of action thathappens from a button click or
whatever gets routed to the model.
Because we wanna be ableto these tests, right?
You should to testwithout touching the view.
And then we have a pretty complicateddependency graph, and I don't want to,

(03:04):
send the entire world into these models.
I want something reallylight and focused so that
these things can dead simple.
Like, I need to fetch thisthing and get back some results.
And so if that dependency.
That, that we were calling is a littlebit obtuse or, you know, it doesn't
fit, doesn't quite fit the needthen, or maybe it requires two other

(03:27):
dependencies to actually 'cause itneeds to pull in data from here and
then consult this list over here inorder to return the right set of data.
I will hide all that stuff in a closure.
And that closure becomesthe, the, the new dependency.
So This is gonna be like a, like a,I'm trying to think of a, an this is
your which will just give you right?

(03:50):
It doesn't need to consult.
Oh, I need to get informationfrom this orders API.
Then I need to get images for theproducts over here or whatever.
And then I need to check to seeif this thing was whatever it is.
You can marry those things in away that they, you encapsulate
all that logic closure and justpass that closure to the model
so that it knows how to fetch data.

(04:11):
And that way your view isn't really
interesting it, you know, yousort of separated responsibilities
in that way and you can ofcourse test all these things.
But it becomes trivial now forthat dependency just by providing
a new closure that just returnsa single item, returns two

Leo Dion (host) (04:31):
Yep.
Yep.

Ben Scheirman (guest) (04:32):
that's another thing we haven't really talked
about, but previews huge superpowerthat I I people were as, as I am.
I think a lot of people just abandonedpreviews 'cause they're kind of kind of
hard, you know, they're hard,
to do.
Right.
Especially in
a big app.

Leo Dion (host) (04:47):
Yeah.
I mean I've had issues withjust like previews not compiling
properly and not and I've justhad to like, I don't want to
abandon 'em 'cause I
want to quickly see stuff.
And if I do wanna usepreviews, what I've ended
up doing at this point is like I usethe preview in a new app that's a test
app.
Right.
And be like, okay, I wantit to look like this.
And then copy that over to

Ben Scheirman (guest) (05:09):
Yeah.
I, so I, I am of the opinion thatlike component and then every list
of that component or whatever likeshould have a preview that contains
all the states and mode, lightmode, dynamic type or whatever.
Empty states, error states, you know,like if you were to look at a design

(05:29):
library from, you know, a web, likea, like for instance like Facebook
or, or Twitter or whatever Airbnb.
I'm just trying to think of like, largeorganizations are gonna have like a.
Like a style guide, likebasically, you can go in and
be like, here's typography.
Here's all the different things you cando, And here's when you should use them.
And these are live examplesthey render right there.

(05:51):
And this is easy to do inthe browser because you're
already in the browser, right?
Like if these things are in HDMLand CSS and JavaScript, well
they can just run it right there.
And so here are all our buttons,here's how you can use how they
respond to hover and clicked anddisabled states and all that stuff.
like the playgrounds, not playgroundsthe previews are our way of doing
that in the best way possible sothat, so that we can see something

(06:15):
that, see how it works, we can
interact with it.
And I would say 90% of my work for thatcollection view component, I, I talked
about 90% of that was doneiterating on a preview in a

Leo Dion (host) (06:27):
And now the last couple years, they're
agnostic as far as whether useSwift UI or UI codes So that's a

Ben Scheirman (guest) (06:33):
They always
were.

Leo Dion (host) (06:34):
They always

Ben Scheirman (guest) (06:36):
you just wrap it your UIV controller
representable and you're done.

Leo Dion (host) (06:40):
Oh

Ben Scheirman (guest) (06:40):
It just now does this for you.
So

Leo Dion (host) (06:43):
to object, right?
And then are you usingCombine underneath

Ben Scheirman (guest) (06:50):
So we use combine where it makes sense
and we use async await for,
Where it makes sense.
And, and I, I've talked about thisbefore where I, I, I think, Johnson
Dell's podcast, we talked about mixingswith do I or sorry, mixing async
await and And like when to use one.
Should we ditch, combine, combines days?
Our guests are numbered.
But I how hard it is to deprecate aframework in Apple land and it go away.

(07:15):
There are just certain thingsthat I just feel like combined
is just, it's just easier toread and write and, async, await
make some make things way easier.
And so so we're still writing new
code that uses combine.
We're still mixing thatsometimes with async weight.
I still don't really think in asyncSo there's very few of that type of
async stream type of I like a a aloop that just runs forever seems

(07:41):
weird to
me.

Leo Dion (host) (07:42):
it does seem weird.

Ben Scheirman (guest) (07:43):
100%

Leo Dion (host) (07:45):
I just wrapped my, I just created my first
Async stream and it's it made sensein that case, but what I've found is
anything that's one of those builtin publishers, like a timer or like
a notification or even key valuestuff, key value observing, it's just
so much easier to do and combine.
And like you said, it's justeasier to think and combine

(08:06):
as opposed to this weird

Ben Scheirman (guest) (08:09):
glad Asy is a thing now, continues.
So like debounce, which I washow would you even write that?
That to me, that I was trying tothink of like, you know, how it,
how it would be written, and that'sjust a different style than, than
writing operators in, in Combine.
But I will say that this isprobably my own just experience

(08:29):
and comfort level with Combine.
I was a holdout on all the programmingI found it to be confusing.
and then
I really dug into it and I
then I was like,
I need to make a course about this.
So that's where theCombined Swift course came
from.
And so now I feel very, verycomfortable in combined.
So of the reason why I'm likenot afraid to keep using it.

Leo Dion (host) (08:48):
I have a new app and I still, I have a couple of and
then everything else is observablebasically and that's I feel like
observable was a thing that'sokay, now I don't need to combine.
Even though I love it like so, yeah.
I totally agree

Ben Scheirman (guest) (09:02):
Yeah.
So the, so the data pieceour app is mostly read only.
So that is, you know, when youhave an app that is taking in
data you know, I, I have,

Leo Dion (host) (09:15):
would an
order?
Would

Ben Scheirman (guest) (09:16):
can't, yeah.
But that's, from myperspective, whole thing, right?
So Like so yes, you know, we couldwrite that, but that's, you know,
luckily it's, it's not the e-commercepart of it is not our responsibility.
But like, say tonal therapy, thisis like the easiest example I
could, I could, come up with,because it's like the only app
that is like kind of standalone.
It doesn't take data fromthe internet and display it.

(09:37):
Like 90% of the apps this you youenter in a frequency of like a tinnitus
frequency that you can hear, andthen this will like, play a pattern.
And so, this is essentially a sliderthat's connected to a text box, so that,
And which is connected to the model.
And so whether or not you adjustthe slider or type in box, they both

(09:57):
end up sort generate a new sequence

Leo Dion (host) (09:58):
right.

Ben Scheirman (guest) (09:59):
and so yeah, that two way binding, it
definitely, you know, still works.
And then if you need to marrythat with an existing architecture
that wasn't built with thesetools you I, feel like I.
Having bindings for the model so thatyou know when it changed and then
glue that to however else you would'veupdated your own internal model.

(10:20):
And I think it's, it's okay to not hato like break your part, your model
up into smaller pieces so that thathas to serve both roles, but you
can have like some glue that youpass a Swift UI to make the Swift
UI call site really nice and cleanand then you glue those two things
together with to the value usingCombine or asy CO eight observation
framework.

Leo Dion (host) (10:41):
Is there anything else you wanna talk about when it comes to
interfacing between UIKit and Swift UI

Ben Scheirman (guest) (10:47):
There's one thing that so I mentioned that
we started on this process of.
Sort of changing out our lists.
So I had to create thiscollection view component.
And, though, one of the early thingswe did to try to get some stuff
working in Swift UI was wrap someexisting UIKit components in Swift UI,

(11:08):
sorry, UIKit components in Swift UI.
So, so using NS or UI viewcontroller representable to wrap an
existing component is essentiallya button, but underneath that is
tons and tons of valuable logicthat we don't wanna mess up, right?
And so just wrap that in Swift UINow the call site is really easy.
It's, we can use it in ourSwift UI views directly.

(11:31):
That happened to be a componentthat needed to be used inside of
a cell and UI hosting controller
that I
mentioned was really nice that youcould just plop in a Swift UI view.
That one will give you a fat warningif you do this, if you have a
so we're, so we're goingfrom UIKit collection view

Leo Dion (host) (11:48):
Is this a runtime Warning, I
assume
is

Ben Scheirman (guest) (11:51):
Runtime warning, you're going from a UI which
is a collection view Swift UI, whichis the hosting configuration view.
inside of that view you have aUI view controller representable.
It will fail, right?
It'll runtime, give you a warning.
This is an unsupportedconfiguration and it will not render

Leo Dion (host) (12:09):
Okay

Ben Scheirman (guest) (12:09):
Because view controllers have to, they have a, an
in variant that you have to satisfy,which is that they have a parent
view controller or they're partof the view controller hierarchy.
And that's how things like safe areaand sets and trait changes and you
know, sizing changes and stuff like thatviewed it, a fear viewed will disappear.

(12:30):
All the, all those things flowthrough the parent child view
controller by putting a Swift UI
Wrapper, a round of view controllerinside of a Swift UI view, and
then putting UI view controllerNow you've broken that like that
little component doesn't have areference to a parent anywhere.
And so I I was running full speed withthis collection thing and the hit a

(12:54):
brick wall with this one and I and andit ended up process and think like,
well, how did Apple implement UI hostingcontroller because it's, or sorry, UI
hosting configuration 'cause it's fast.
That was the other thing fastworried about is like the UI hosting
view has a generic of a root viewUI hosting controller, sorry,
has a generic of that root view.

(13:16):
And if you, and it's mutable so youcan swap out that view for another one.
And that's what UI hosting cell.
So it's just, it's keepingthat same space reserved.
There's only one UI view in there,so you're not like constantly
creating new UI views and then de andallocating them as you scroll, right?
It's one of those, but then youswap, swap in and out the, the Swift
UI content and that is really fast.

(13:38):
So I went that embeds a UI hostingcontroller of a known view type.
And then that one hasa method on it where I
can set its parent So
that I know I have a way toset the parent view controller
of that UI hosting controller.
This is kind of hard tosay on podcast form, but

Leo Dion (host) (13:59):
So

Ben Scheirman (guest) (14:00):
so, I sort of
like, how, how did Apple implementUI hosting configuration?
Like they're, they're using UIcollection view cell, so like
they're probably using UI hosting
controller.
So I went that route and did it manuallyand I was able to set that parent view
controller manually and it wasn't,
it was probably a dozen linesof code to get this done.

(14:21):
And so it

Leo Dion (host) (14:22):
that is something people
should watch out
for, the hierarchy.
Yeah.
You're, it's not
gonna

Ben Scheirman (guest) (14:28):
yeah.
And it like, when I out, I'mlike, oh we're going UIKit oh
UI to UIKit to kit to Swift UIto UIKit like, and it does work.
But you gotta be aware of allthese layers because, the way that
Swift UI does sizing and layout isdifferent from the UIKit does and
and those Swift UI doesn't careabout your auto layout constraints.

(14:50):
it cares about your.
Yeah, yeah.
This has taken me a to to internalize.
But I will say like the, the littletidbit that has helped is if you have
an intrinsic content size for a viewor a preferred content size for a view
controller if you save fixed size on theSwift UI wrapper, it will adhere to that

(15:10):
size as if it were the that component.
And that a bunch because I was like, howdo to know how big the And the answer
is intrinsic content size for views,preferred content size for controllers,
and then use the dot fixed size,
Modifier on the Swift UI site.

Leo Dion (host) (15:28):
We had one question from Swift Dev when using built in
views, for example, a CN contactview controller or an EK event view
controller in Swift UI is therea way to have the toolbar showing
without wrapping set controller ina UI navigation I know the easiest
solution is to put it in a sheet,which is then, which isn't, which.

(15:51):
Which then just a UInavigation controller without
a ui, Swift UI navigation.
But I'm wondering if there's a wayto do it without using a sheet.
If you wrap it a UI view CONTnavigation controller, it's already
in Swift UI navigation stack.
It will show two navigation bars.
If you don't wrap it in aUI navigation controller, it
won't show the edit button.

(16:13):
Do you know what this Do

Ben Scheirman (guest) (16:17):
situation is
bar.
Obviously we I guess the questionis, is the component, is Apple's
component coming with its own navigationcontroller, or does it expect you to
right
your And,
right two that were mentionedwere the contact picker
and what was the other one?

Leo Dion (host) (16:32):
The event view controller for event

Ben Scheirman (guest): for like calendar. (16:35):
undefined
Okay.
Yeah, I mean I would these areboth, these, both predate Swift
UI, the contact one by a lot.
Yeah
I would
I
would not, I I would just try tolike make that controller happy in
whatever way made sense for thatcontroller, which probably means
playing UIKit navigationcontroller in a sheet.

(16:56):
If you, I also think that, that thosethings are generally modal in behavior
anyway.
You like, you go thereto a thing then you
dismiss it and now you're

Leo Dion (host) (17:03):
It your it should be like a little
I

Ben Scheirman (guest) (17:07):
I, I push this on your own navigation stack.
oh, I fill out some details and now Iclick next, and now like, next hierarchy
is Apple's UI for picking a contact.
That me.

Leo Dion (host) (17:16):
Yeah 100% I agree.
Yeah.
I had one other topic I wanted to cover.
Now that you're here we talkedabout Swift Package Manager.
What is that, I guess at Nike?

Ben Scheirman (guest) (17:30):
There's probably too many internal details to
to discuss.
Large companies move slowly, right?
We have a

Leo Dion (host) (17:36):
of

Ben Scheirman (guest) (17:37):
lot projects.
of
yeah, it's, it's it's.

Leo Dion (host) (17:42):
Is it on the goal
post
Is

Ben Scheirman (guest) (17:45):
yeah, yeah, yeah.
We actually hit a blocker.
We, we were gonna do it last year andwe hit a major blocker and have engaged
Apple in trying to out But yeah, it's,know, like big companies do things in
unique ways, I think sometimes, andsometimes that match the ideal path
that most people would encounter.
So I don't think most peoplewould even be that we run into.

(18:05):
So

Leo Dion (host) (18:06):
yeah.
Yeah.
that makes sense.
So.
One thing that you helped meon was introducing me to sub
re and that was a big benefit.
I'm right now in the middle ofa rewrite of one of my packages.
but do you think the situation hasimproved with developing simultaneous
package development when youhave like dependencies and stuff?

Ben Scheirman (guest) (18:27):
I Do
no, I don't think it's improved at all.
So, so maybe some contextfor the listeners.
You monorepo, which is everythingthat your company develops, all
everything or in your own repo.
You can still do third party stuffthat comes in externally, but if you
want to iterate on those componentswhile you're building a thing, which

(18:48):
is what we most, most of the timewe do, then, then having them in one
repo is actually kind of nice and it,
It, it's not even my preference.
I just
think that there are benefits, right?
So like the, the, the
alternative is like everycomponent that you have
has a separate
GitHub repo or GI Gitrepository somewhere maybe on

Leo Dion (host) (19:08):
in either a

Ben Scheirman (guest) (19:09):
I'm specifically

Leo Dion (host) (19:10):
ta
either I was just gonnasay, I'm specifically
talking
about like a swift, like an opensource project you wanted to publish

Ben Scheirman (guest) (19:19):
But it,
has other packagesthat are part of that.

Leo Dion (host) (19:23):
Yeah like third, park, like you want a,
different plugin for instance

Ben Scheirman (guest) (19:29):
Yeah.
And are
hosted in the same repoor, or in separate repos.

Leo Dion (host) (19:33):
Right, right.
But it's put But

Ben Scheirman (guest) (19:35):
If you put
'em in

Leo Dion (host) (19:36):
put
But it's hard harderto publish it, like as
a mono repo.
So, for instance, in my case I have a,I'm working on sublimation, which is
my package for allowing people to auto,like if you have a iPhone, you want
it to auto detect your vapor server.
It, you could either advertise itvia ngrok and some sort of key value
pair on the cloud, or you could useBonjour and advertise it that way.

(20:00):
So there's separate packages for that.
That's the current example thatI'm running into right now.
So right it's actually a monorepo, and then I'm gonna split
them off into in development,like not extra not advertised
yet, but like it's in a mono repo.
And then the plan is to takethose directories and put
'em out into separate repos.
Once I know that everything works

Ben Scheirman (guest) (20:22):
Yeah.
I think that that.
So like if you wanted to iterateon all those things, but keep
them in separate repos, thenyou could do a local checkout.
You could tell your package manager theSwift package manager, that I have a
local package instead of a remote one.

Leo Dion (host) (20:34):
Yep.
That's what

Ben Scheirman (guest) (20:35):
what I'm doing
that way.
In the CocoaPods way, if anythingin your pod file reference
to Local up under developmentdependencies and symlinked to those
folders in your Xcode project.
So when, could you could edit themdirectly you when done, you push
it, you tag it, you change yourpod file reference to point to
the tag version and you're done.

(20:56):
It was actually pretty nice storyin, in swift Package a little bit
more cumbersome to do that, I think.
And I, I haven't, like, I use SwiftPackage Manager on basically every
project I do, but it's, all of thoseare tiny in comparison to what, to
what I'm working on at, at Nike.
But, there are certain things that Ihave heard have been problematic on

(21:19):
larger projects like of creating a localversion of a transit of dependency.
So say I have dependency A, buta a which I want to work on.
And so pulling in dependency B locally,when you resolve A, you need Swift
package manager to also as a localpackage so that, so that it all I
don't know if that's solved yet.
I then there's the the other problemof like, X code decides to resolve

(21:42):
packages when it wants to, again,I know this is but if you've got a
bunch of packages and then you geton a plane and open up a project.
Like, up your editor whileit's it's to packages.
And I, I kind of of of CocoaPodswhere you're like manually saying,
I'm ready to pod install here.
And at that point you've got acopy of the, the code Twist is

(22:02):
actually a, a project thatI'm really interested in.

Leo Dion (host) (22:06):
Yeah.
I've had Pedro
on here
talking about tourist and I feel

Ben Scheirman (guest): They do the, they do (22:09):
undefined
They do
I
does amazing
you have a command toresolve the packages.
It does it with Swift PackageManager, checkout and then when
you integrate with Twist, it
uses
that local version.

Leo Dion (host) (22:23):
Yeah.
Yeah.
Completely.
Anything else Ben, you wanna talk about
before we close out

Ben Scheirman (guest) (22:30):
Oh, I could talk about this stuff all day

Leo Dion (host) (22:33):
How much time do you did you still wanna chat
about this wonderful studiothat I'm about to tear down I.
wonderful

Ben Scheirman (guest) (22:38):
you want to.
Sure.
to tear

Leo Dion (host) (22:39):
Okay, well end it
far the podcast episode, and recorda separate thing and I'll post a
link to that in the show notes.
Ben, thank you
was

Ben Scheirman (guest) (22:52):
Yeah.
it really great conversation.
Appreciate it.

Leo Dion (host) (22:54):
Where could people find you online

Ben Scheirman (guest) (22:56):
I
You can find website@benScheirman.com
That will have links to n and combineSwift and some of the other apps
I work and I'm on Mastodon at ben
s@mastodon.xyz.

Leo Dion (host) (23:09):
Awesome.
People can find me on Twitter at Leo
Dion.
At Leo g Dion at am on Mastodon.
If you wanna come on let me know.
I'd love to have you on as a guest.
If you're watching this onYouTube, please and subscribe.
I greatly
Advertise With Us

Popular Podcasts

On Purpose with Jay Shetty

On Purpose with Jay Shetty

I’m Jay Shetty host of On Purpose the worlds #1 Mental Health podcast and I’m so grateful you found us. I started this podcast 5 years ago to invite you into conversations and workshops that are designed to help make you happier, healthier and more healed. I believe that when you (yes you) feel seen, heard and understood you’re able to deal with relationship struggles, work challenges and life’s ups and downs with more ease and grace. I interview experts, celebrities, thought leaders and athletes so that we can grow our mindset, build better habits and uncover a side of them we’ve never seen before. New episodes every Monday and Friday. Your support means the world to me and I don’t take it for granted — click the follow button and leave a review to help us spread the love with On Purpose. I can’t wait for you to listen to your first or 500th episode!

Crime Junkie

Crime Junkie

Does hearing about a true crime case always leave you scouring the internet for the truth behind the story? Dive into your next mystery with Crime Junkie. Every Monday, join your host Ashley Flowers as she unravels all the details of infamous and underreported true crime cases with her best friend Brit Prawat. From cold cases to missing persons and heroes in our community who seek justice, Crime Junkie is your destination for theories and stories you won’t hear anywhere else. Whether you're a seasoned true crime enthusiast or new to the genre, you'll find yourself on the edge of your seat awaiting a new episode every Monday. If you can never get enough true crime... Congratulations, you’ve found your people. Follow to join a community of Crime Junkies! Crime Junkie is presented by audiochuck Media Company.

Ridiculous History

Ridiculous History

History is beautiful, brutal and, often, ridiculous. Join Ben Bowlin and Noel Brown as they dive into some of the weirdest stories from across the span of human civilization in Ridiculous History, a podcast by iHeartRadio.

Music, radio and podcasts, all free. Listen online or download the iHeart App.

Connect

© 2025 iHeartMedia, Inc.