246: Hard Forks
00:00:00
◼
►
- Welcome to Under the Radar,
00:00:01
◼
►
a show about independent iOS app development.
00:00:04
◼
►
I'm Marco Arment.
00:00:05
◼
►
- And I'm David Smith.
00:00:06
◼
►
Under the Radar is usually not longer than 30 minutes,
00:00:08
◼
►
so let's get started.
00:00:09
◼
►
- With this episode, I've been facing a lot of
00:00:13
◼
►
angst and stress about the giant weight
00:00:17
◼
►
of my huge amount of legacy UI code in my app.
00:00:21
◼
►
Because my app, it's eight years old now,
00:00:24
◼
►
and over that time, we've had both Swift itself
00:00:29
◼
►
and then later Swift UI come out,
00:00:32
◼
►
in addition to just huge advances in UIKit under the hood.
00:00:36
◼
►
And if I stay with UIKit, huge advances there
00:00:39
◼
►
in the meantime.
00:00:40
◼
►
And so I have all this huge mountain of legacy code
00:00:43
◼
►
in my app that gives me a lot of stress
00:00:46
◼
►
and makes it hard for me to make changes
00:00:49
◼
►
and move forward and update the design and things like that.
00:00:51
◼
►
And so I have thought for a while,
00:00:53
◼
►
man, wouldn't it be nice to just start clean
00:00:57
◼
►
and do a whole clean, fresh start
00:01:00
◼
►
and rewrite the entire UI.
00:01:02
◼
►
And that's usually a terrible idea
00:01:05
◼
►
because it's akin to a large rewrite of your app.
00:01:09
◼
►
And so usually I've talked myself out of that
00:01:12
◼
►
because it just seems like this impossible mountain to climb.
00:01:16
◼
►
And a few weeks ago, you mentioned
00:01:19
◼
►
an interesting alternative.
00:01:22
◼
►
That you said, why don't you just start building it
00:01:25
◼
►
and make just this fork in the app code.
00:01:28
◼
►
And either when you're ready or maybe only on the latest iOS
00:01:34
◼
►
version or whatever it is, in certain test modes,
00:01:37
◼
►
whatever it is, when you're ready,
00:01:38
◼
►
just switch over to that UI conditionally
00:01:41
◼
►
and still have all the old code there
00:01:43
◼
►
in the app for when it's not running in that mode
00:01:45
◼
►
or under those conditions.
00:01:47
◼
►
And I thought, it's one of those things
00:01:48
◼
►
like a programmer first hears that
00:01:50
◼
►
and that's a terrible idea, maintenance, et cetera.
00:01:52
◼
►
And then it starts infecting your brain a little bit.
00:01:54
◼
►
And you've done this to me before.
00:01:56
◼
►
It's one of those ruthlessly efficient and pragmatic things
00:02:01
◼
►
that you introduced to my thought technologies.
00:02:04
◼
►
I would originally think-- like when you first told me that you
00:02:07
◼
►
stored your Git checkouts for your Macs in Dropbox,
00:02:10
◼
►
I thought that was the craziest thing I'd ever heard.
00:02:12
◼
►
And I'm like, wait a minute.
00:02:13
◼
►
But then you can work on it on the laptop and the desktop.
00:02:16
◼
►
You don't have to constantly be committing things just
00:02:18
◼
►
to transfer to a different computer.
00:02:19
◼
►
Interesting.
00:02:21
◼
►
And so the idea of having an entirely separate UI branch
00:02:26
◼
►
within my app, that sounds ridiculous.
00:02:29
◼
►
And it sounds like a very impure thought to a programmer.
00:02:34
◼
►
But the more I think about it, the more I think,
00:02:37
◼
►
I actually might do that.
00:02:39
◼
►
And I want to actually talk about it.
00:02:41
◼
►
I want to actually get more input on that from you.
00:02:45
◼
►
And let's elaborate on that and see, what does that look like?
00:02:48
◼
►
Why would you do such a thing?
00:02:50
◼
►
And are you doing such a thing in any recent stuff?
00:02:53
◼
►
I'm glad it was an interesting thought to you.
00:02:56
◼
►
And I think it is definitely an approach
00:02:58
◼
►
that I've taken before.
00:02:59
◼
►
And I think it is one of those things that is certainly not
00:03:02
◼
►
the case for everything, that typically, I suppose,
00:03:04
◼
►
the way that we evolve our apps is this kind of incremental--
00:03:09
◼
►
replacing one bit-- it sort of becomes the ship of Theseus
00:03:12
◼
►
or whatever, where it's just like you keep changing one
00:03:14
◼
►
little bit at a time.
00:03:16
◼
►
And eventually, you end up with something new.
00:03:18
◼
►
But over the course of that progression, that change,
00:03:23
◼
►
at no point was there this hard change
00:03:25
◼
►
from one thing to the other.
00:03:26
◼
►
And I think that approach has a lot of merit.
00:03:28
◼
►
But it also means that you're always tied to the past.
00:03:32
◼
►
You're always tied to your old way of doing things.
00:03:35
◼
►
And you have to be balancing all of these things
00:03:38
◼
►
while you're moving forward.
00:03:39
◼
►
Because you're also-- it's one of my favorite gifts.
00:03:44
◼
►
I think it's from Wallace and Gromit, where Gromit is
00:03:47
◼
►
building the train track in front of his toy train
00:03:50
◼
►
as he's riding it.
00:03:51
◼
►
And he's just constantly building just that little bit
00:03:53
◼
►
in front of him as he goes.
00:03:55
◼
►
And that approach means that you always
00:03:57
◼
►
have to have that sense of urgency,
00:03:59
◼
►
that you're in this weird incremental process,
00:04:01
◼
►
that you're building things.
00:04:02
◼
►
But you're building things that are alive and in active use.
00:04:04
◼
►
And so if anything goes wrong, bad things will happen.
00:04:07
◼
►
And so instead, taking the approach of saying,
00:04:09
◼
►
you know what, I'm going to completely start from zero,
00:04:13
◼
►
essentially.
00:04:14
◼
►
And it's not zero insofar as-- well, it's zero code.
00:04:17
◼
►
It's not zero in terms of experience,
00:04:19
◼
►
in terms of expectation.
00:04:20
◼
►
You know how the app should work.
00:04:21
◼
►
You know what it should do.
00:04:22
◼
►
You have something to compare it to.
00:04:24
◼
►
And free yourself from trying to have
00:04:27
◼
►
this be an incremental thing and instead do a complete rewrite.
00:04:29
◼
►
And for me, the first place I had this big version of this
00:04:33
◼
►
was back when SwiftUI was introduced to watchOS.
00:04:37
◼
►
So previous to SwiftUI's introduction to watchOS,
00:04:40
◼
►
we had WatchKit, which was awful and really rough to use
00:04:43
◼
►
and not fun at all.
00:04:45
◼
►
And didn't allow a lot of cool, interesting, and fluid UIs
00:04:49
◼
►
that you might want to build.
00:04:50
◼
►
But then out comes SwiftUI, but it requires watchOS 6.
00:04:55
◼
►
And so I felt in this really awkward place,
00:04:57
◼
►
because I didn't want to feel like--
00:04:59
◼
►
I couldn't require watchOS 6 right off the bat.
00:05:02
◼
►
Because if I did, especially with the watch,
00:05:04
◼
►
it creates this really weird experience
00:05:06
◼
►
where the app just gets uninstalled from the watch
00:05:08
◼
►
and weird things start happening.
00:05:10
◼
►
And so I needed to keep my deployment target sort
00:05:13
◼
►
of generous.
00:05:15
◼
►
But I still wanted to use SwiftUI.
00:05:16
◼
►
And so what I ended up doing with that app
00:05:18
◼
►
is I just left the WatchKit version of the app
00:05:22
◼
►
entirely as it was.
00:05:23
◼
►
Like it's frozen in carbonite.
00:05:24
◼
►
It is just right there.
00:05:26
◼
►
And then on the Swift, then just have built out the SwiftUI app
00:05:32
◼
►
that I'd always wanted to build that I thought was great.
00:05:34
◼
►
And I went and built that.
00:05:36
◼
►
And then in essentially the app delegate,
00:05:38
◼
►
when the app is being run, which entry point the app got
00:05:41
◼
►
was just based on, are you running watchOS 6?
00:05:44
◼
►
You get this one.
00:05:45
◼
►
If you're watching watchOS 5 or before,
00:05:47
◼
►
you get the old version.
00:05:49
◼
►
And when I did this, in some ways,
00:05:51
◼
►
it was forced, because I wanted to use SwiftUI so soon,
00:05:54
◼
►
to go down this road.
00:05:55
◼
►
And I was curious to see what the result would be.
00:05:59
◼
►
Because inevitably, what I was doing
00:06:00
◼
►
was I was creating a situation where there were going to be
00:06:03
◼
►
people who would see in the screenshot some
00:06:06
◼
►
of the stuff that was there for the SwiftUI version in the app
00:06:10
◼
►
Or maybe a friend of theirs or a spouse, whatever.
00:06:14
◼
►
They see someone else who has the app, and they--
00:06:16
◼
►
why doesn't my app look like that?
00:06:18
◼
►
And I was bracing for that to be an annoyance and a customer
00:06:22
◼
►
service issue and creating confusion.
00:06:23
◼
►
And I think in reality, it just happens much less often.
00:06:27
◼
►
Because for most people, their experience of--
00:06:31
◼
►
very often, people are more likely to be upset by just
00:06:35
◼
►
any change than they are by the app just staying
00:06:39
◼
►
the same as it was before.
00:06:41
◼
►
And if anyone is running the old version,
00:06:43
◼
►
they're getting exactly the same experience
00:06:45
◼
►
that they're used to that's been there forever.
00:06:47
◼
►
And then the new people, hopefully their experience
00:06:49
◼
►
is positive.
00:06:49
◼
►
And I got a little bit of people who were confused as to,
00:06:52
◼
►
why don't I get this cool graph or the nice animations
00:06:56
◼
►
or any of the features that were in there?
00:06:58
◼
►
But by and large, that didn't happen.
00:07:00
◼
►
And I really liked it.
00:07:01
◼
►
It was a really pleasant way to develop,
00:07:04
◼
►
because I was building the app--
00:07:07
◼
►
when we're first writing an app, I
00:07:08
◼
►
feel like one of the hardest things
00:07:10
◼
►
is we don't know what the app is ultimately
00:07:12
◼
►
going to look like, what it's ultimately going to do,
00:07:15
◼
►
how to structure it, how to build it.
00:07:17
◼
►
And that is just inherent to the initial creation,
00:07:21
◼
►
that we build an app, and then it's
00:07:23
◼
►
going to go through iteration and refinement
00:07:25
◼
►
and get feedback from people and interact
00:07:28
◼
►
with the real world in a way that informs us
00:07:32
◼
►
on how the app should actually work in practice.
00:07:34
◼
►
And so rewriting it-- in this case,
00:07:37
◼
►
when I was rewriting the Pedometer++ WatchKit app,
00:07:42
◼
►
the second app was actually what people wanted,
00:07:44
◼
►
was actually what people used, was much better,
00:07:47
◼
►
was much more performant, did all the things right.
00:07:50
◼
►
And I was glad to be able to do this hard fork approach.
00:07:55
◼
►
And having had that experience, I've
00:07:58
◼
►
opened myself to this in a lot more contexts.
00:08:01
◼
►
And I think in general, it's a way to deal with iOS versioning
00:08:05
◼
►
is probably the main place to do this.
00:08:06
◼
►
Like in your case, I think taking the approach of saying,
00:08:10
◼
►
well, even though you don't strictly need to, say,
00:08:12
◼
►
I'm going to remake the main UI in Overcast in SwiftUI,
00:08:19
◼
►
but I'm going to target iOS 16's version of SwiftUI
00:08:24
◼
►
and only do that.
00:08:26
◼
►
And while technically you could go, I think, all the way back
00:08:28
◼
►
to iOS 13, I think, with SwiftUI,
00:08:32
◼
►
if you go back farther-- the farther you go back,
00:08:35
◼
►
the more complicated it is to deal with compatibility,
00:08:37
◼
►
with issues, with SwiftUI rendering differently
00:08:39
◼
►
in two different ways.
00:08:40
◼
►
If you go with the latest and greatest,
00:08:42
◼
►
like once the sort of initial builds and beta stuff gets out
00:08:45
◼
►
of the way, you'll be on a much more stable, much more smooth
00:08:48
◼
►
ground going forward.
00:08:49
◼
►
And then at some point, yeah, you just turn that on.
00:08:52
◼
►
And depending on how different you make the app,
00:08:54
◼
►
many people may not even notice.
00:08:56
◼
►
But either way, you're in this really nice, clean place
00:08:59
◼
►
that you have this beautiful, clean bit of code that's
00:09:01
◼
►
all Swift, it's all modern, uses all the latest and greatest.
00:09:05
◼
►
And then over time, the old version just kind of falls away.
00:09:08
◼
►
And if you're gaining it based on iOS version,
00:09:10
◼
►
eventually you'll stop supporting iOS 15.
00:09:13
◼
►
And when you do that, the old version
00:09:14
◼
►
just disappears from the app and will never be used again.
00:09:17
◼
►
That fork will die, and you're just
00:09:19
◼
►
sort of living on the new fork.
00:09:20
◼
►
And yeah, it's a little crazy.
00:09:22
◼
►
It's a little wild.
00:09:23
◼
►
I understand why some people would think that it's
00:09:26
◼
►
a bit of a weird way to go.
00:09:27
◼
►
But I got to say, I really liked it.
00:09:30
◼
►
And it's worked well for me in the past.
00:09:32
◼
►
And it's like, I'm going to keep using this pattern, I think,
00:09:34
◼
►
going forward for other projects that I'm working on this summer.
00:09:37
◼
►
Yeah, that's really-- it's a very, very interesting way
00:09:41
◼
►
to look at things.
00:09:43
◼
►
I mean, it's a very pragmatic way,
00:09:45
◼
►
as you are so good at introducing to my thoughts.
00:09:50
◼
►
I want to do something like this in theory.
00:09:53
◼
►
In practice, I'm not sure I will be able to go through with it.
00:09:57
◼
►
I mean, so when I did the same transition on watchOS
00:10:01
◼
►
that you were just talking about, when Swift UI came out
00:10:03
◼
►
and replaced the god-awful watch kit, I was very--
00:10:07
◼
►
I was reluctant to do that at first.
00:10:09
◼
►
And I talked to you about it.
00:10:10
◼
►
And you basically told me, just right from scratch,
00:10:13
◼
►
write it fresh, see how long it takes.
00:10:14
◼
►
And it ended up taking not that long.
00:10:16
◼
►
And I didn't regret that decision at all.
00:10:18
◼
►
It was great.
00:10:19
◼
►
The outcome was great.
00:10:20
◼
►
That has been like a thorn in my mind ever since then.
00:10:26
◼
►
Because when I think about doing it on the iOS app, which
00:10:30
◼
►
is a much larger task, because there's so much more UI there,
00:10:34
◼
►
and it's more complicated.
00:10:35
◼
►
But when I think about doing it there,
00:10:37
◼
►
my first thought is, no, I shouldn't do that,
00:10:40
◼
►
because it won't work out.
00:10:41
◼
►
It'll take forever.
00:10:42
◼
►
I'll regret it.
00:10:43
◼
►
And then that damn watch app, I realized,
00:10:46
◼
►
but it worked really well there.
00:10:50
◼
►
And that keeps being this exception in my mind.
00:10:55
◼
►
But look over here.
00:10:57
◼
►
And you didn't regret it.
00:10:58
◼
►
And it was great.
00:10:59
◼
►
So that's what has kept this kind of spark burning in my mind,
00:11:03
◼
►
like maybe I should actually do this.
00:11:05
◼
►
It's tough, because SwiftUI, it still
00:11:09
◼
►
feels like you're using beta 1 of the framework.
00:11:13
◼
►
And right now, using the iOS 16 stuff,
00:11:14
◼
►
it actually is very much still early beta in certain ways.
00:11:17
◼
►
And there's still some frustrating bugs.
00:11:19
◼
►
But SwiftUI in general still feels very beta to me.
00:11:22
◼
►
So it's hard for me to get very far with SwiftUI on iOS.
00:11:28
◼
►
On watchOS, it's easy, because it's simple.
00:11:31
◼
►
The needs of navigation and viewed complexity and stuff
00:11:34
◼
►
on watchOS are so much lower than on iOS,
00:11:37
◼
►
because it's such a simpler platform.
00:11:39
◼
►
But on iOS, there are certain expectations
00:11:42
◼
►
of how things should work, how things should behave,
00:11:44
◼
►
how things should look, the kind of customization people expect.
00:11:47
◼
►
And that's just really hard in certain ways with SwiftUI.
00:11:51
◼
►
You hit a lot more walls.
00:11:52
◼
►
You hit them more frequently, and you hit them harder.
00:11:54
◼
►
And so I feel like while the transition on watchOS
00:11:58
◼
►
was relatively smooth, the transition on iOS
00:12:02
◼
►
probably is less so.
00:12:03
◼
►
And at the same time, if I'm going
00:12:05
◼
►
to do a big rewrite like this-- because again,
00:12:08
◼
►
I have two problems.
00:12:09
◼
►
Well, three, really.
00:12:10
◼
►
I'm using old versions of UIKit, and there
00:12:12
◼
►
are newer things in UIKit that can make things simpler.
00:12:15
◼
►
I'm using still mostly Objective-C,
00:12:17
◼
►
and I want to make most of that, or all of it, Swift.
00:12:20
◼
►
And I'm not using SwiftUI, and that's clearly
00:12:23
◼
►
what Apple is pushing as the way we should be doing things.
00:12:26
◼
►
So I need to move to SwiftUI.
00:12:27
◼
►
So ideally, if I'm going to do this big rewrite, given
00:12:31
◼
►
how long it takes me to adopt new things,
00:12:33
◼
►
this is the kind of thing I want to do it once
00:12:36
◼
►
for a very long time.
00:12:37
◼
►
I don't want to just jump to Swift with UIKit
00:12:41
◼
►
if I can go right to SwiftUI.
00:12:44
◼
►
And then that, I think, will buy me more time
00:12:47
◼
►
with this new platform down the road.
00:12:48
◼
►
And I'll be able to do certain things faster and more
00:12:51
◼
►
efficiently.
00:12:52
◼
►
It's just the matter of when I hit those walls,
00:12:54
◼
►
and how many walls do I hit.
00:12:55
◼
►
And I mean, so far, I'm hitting a lot of them.
00:12:57
◼
►
But part of that's because I don't know it as well.
00:13:00
◼
►
SwiftUI is more complicated.
00:13:02
◼
►
I also have to deal with the fact
00:13:03
◼
►
that SwiftUI has to access state and changes in certain ways.
00:13:10
◼
►
And my underlying model layers are still mostly Objective-C.
00:13:13
◼
►
I have some Swift in there, some Swift shims on top of it
00:13:16
◼
►
to make SwiftUI possible.
00:13:18
◼
►
But most of that is still not Swift.
00:13:21
◼
►
And so-- and certainly not SwiftUI,
00:13:24
◼
►
not like the combined publishable kind of models
00:13:28
◼
►
that SwiftUI works on.
00:13:29
◼
►
So if I'm going to go on SwiftUI,
00:13:31
◼
►
I also have to do a whole bunch of that lower level changing
00:13:35
◼
►
and bringing things up to date at the lower levels,
00:13:38
◼
►
and simplifying certain things, rewriting certain things,
00:13:41
◼
►
or putting shims on top of them.
00:13:42
◼
►
So there's a lot more work to do for me to do this.
00:13:45
◼
►
And so the risk is much greater.
00:13:48
◼
►
But yet, I still feel like I probably should do it anyway,
00:13:51
◼
►
because I still feel all this weight of this old code.
00:13:55
◼
►
And it holds me back.
00:13:57
◼
►
And it makes me-- I get this brain freeze.
00:14:00
◼
►
It's hard for me to even work on my app
00:14:02
◼
►
right now, because I'm blocked by so many of these things.
00:14:07
◼
►
And if I can just unfreeze my brain and plow through,
00:14:12
◼
►
I feel like I need something to do that.
00:14:14
◼
►
And maybe this giant modernization project is that.
00:14:18
◼
►
But I don't know.
00:14:19
◼
►
That seems like a tall order.
00:14:21
◼
►
We are brought to you this episode by Sourcegraph.
00:14:24
◼
►
So you've hired a brilliant developer.
00:14:26
◼
►
That's great.
00:14:27
◼
►
Now you have to get them onboarded.
00:14:28
◼
►
If your company is growing, onboarding new developers
00:14:30
◼
►
is a common occurrence.
00:14:31
◼
►
But it's a big undertaking each time.
00:14:33
◼
►
One of the biggest challenges is to getting new hires up
00:14:36
◼
►
to speed with their team's project.
00:14:38
◼
►
This can be tricky if the code bases your developers are
00:14:40
◼
►
working in are already very large.
00:14:42
◼
►
So thankfully, Sourcegraph makes it easy to move quickly,
00:14:45
◼
►
even in those big code bases.
00:14:47
◼
►
Developers know that knowledge is most useful
00:14:49
◼
►
when it's findable.
00:14:51
◼
►
Centralization is helpful.
00:14:52
◼
►
But given the fact that most companies store knowledge
00:14:54
◼
►
in at least two different locations,
00:14:56
◼
►
how do you make knowledge accessible to those who need it?
00:14:58
◼
►
As a code intelligence platform, Sourcegraph
00:15:01
◼
►
gives developers what they need to drive their own learning
00:15:03
◼
►
over time and in different situations.
00:15:06
◼
►
Teams without Sourcegraph need to rely on asking colleagues
00:15:09
◼
►
or reviewing documentation that may be out of date, which
00:15:11
◼
►
is cumbersome and time consuming.
00:15:13
◼
►
But with Sourcegraph, every developer
00:15:15
◼
►
can search across millions of repositories
00:15:17
◼
►
to find specific code, saving time for themselves
00:15:19
◼
►
and everyone else.
00:15:21
◼
►
So when questions do come up, you
00:15:22
◼
►
know it's the big stuff that's worthy of the extra time.
00:15:25
◼
►
Sourcegraph was created to make developers' lives easier.
00:15:28
◼
►
And today, they work with leading companies
00:15:30
◼
►
across every industry, including three out of five
00:15:32
◼
►
of the top tech companies, plus PayPal, Uber, Plaid, GE, Reddit,
00:15:36
◼
►
and Atlassian.
00:15:38
◼
►
Visit about.sourcegraph.com to learn more.
00:15:41
◼
►
That's about.sourcegraph.com to find out
00:15:45
◼
►
why some of the biggest tech companies in the world
00:15:47
◼
►
use Sourcegraph and to see what it can do for yours.
00:15:49
◼
►
Or to click the link in the show notes
00:15:51
◼
►
to let them know that you heard about them from us.
00:15:53
◼
►
Our thanks to Sourcegraph for their support of this show
00:15:56
◼
►
and Relay FM.
00:15:57
◼
►
So I think that there's two things that really come to mind
00:16:00
◼
►
as you unpack the resistances or the issues
00:16:03
◼
►
that you feel like you're coming up against.
00:16:05
◼
►
And it's like, I think the first one is there's the reality
00:16:09
◼
►
that if we never changed our apps at all,
00:16:13
◼
►
like if you just left the version that you have right now
00:16:15
◼
►
in the App Store, the amount of time
00:16:18
◼
►
that it would be that that would just work fine and be great
00:16:23
◼
►
for most of your users is surprisingly long.
00:16:28
◼
►
It's something that, barring potentially like weird--
00:16:31
◼
►
there's a new screen size such that the app gets letterboxed
00:16:36
◼
►
if it isn't rebuilt or something like that,
00:16:38
◼
►
which is relatively easy to fix.
00:16:41
◼
►
It's a weird thing to think that that really old code could just
00:16:44
◼
►
exist for a long time.
00:16:46
◼
►
And I think accepting that, accepting that that old code
00:16:49
◼
►
isn't necessarily bad or needs to be changed or modernized
00:16:53
◼
►
and kept current is freeing in this way.
00:16:56
◼
►
That I think viewing it that you have this ability
00:16:59
◼
►
to draw a boundary around where the new stuff is going to go
00:17:02
◼
►
and the old stuff is just working like it always has been
00:17:05
◼
►
and always will be, and that this new version is
00:17:08
◼
►
different and distinct from it.
00:17:09
◼
►
And I think for me, it would be the freedom
00:17:12
◼
►
of being able to say, the old version is fine.
00:17:14
◼
►
And if that's-- well, in theory, you think,
00:17:17
◼
►
oh, I don't want to have to maintain
00:17:18
◼
►
both versions of my app.
00:17:20
◼
►
Now it's like, now I have two things to manage.
00:17:23
◼
►
That's technically true.
00:17:25
◼
►
But in practice, in reality, I think
00:17:28
◼
►
isn't actually what happens in practice.
00:17:30
◼
►
That more often than not, the old stuff is mostly fine.
00:17:33
◼
►
And it won't actually cause problems or issues for you.
00:17:36
◼
►
Because that's just the reality.
00:17:38
◼
►
One of the best things about being an independent developer
00:17:42
◼
►
is when I go on vacation, and I'll go away
00:17:44
◼
►
for a couple of-- go away for two weeks, come back,
00:17:47
◼
►
and everything's still the same as it was.
00:17:49
◼
►
Everything's still working.
00:17:50
◼
►
It's not like servers.
00:17:51
◼
►
It's not like something where you have this--
00:17:53
◼
►
there's this sense of this active energy has
00:17:55
◼
►
to be poured into the system in order
00:17:57
◼
►
to keep it going, that an app that
00:17:59
◼
►
is in a good, stable place that isn't full of bugs
00:18:03
◼
►
or something like that, once it reaches this equilibrium point,
00:18:07
◼
►
it can sit there for a very long time.
00:18:10
◼
►
And I think the other thing that really just popped
00:18:13
◼
►
into my head was the thought that something like SwiftUI
00:18:16
◼
►
and something like a rewrite is also an opportunity
00:18:20
◼
►
to change the way that you are approaching things
00:18:26
◼
►
and to not just modernize your code,
00:18:29
◼
►
but also to modernize your thinking, your structure,
00:18:33
◼
►
the way that you're building things.
00:18:35
◼
►
And I can say from my own experience,
00:18:37
◼
►
having built a lot of apps now in SwiftUI--
00:18:40
◼
►
and WidgetSmith is essentially entirely SwiftUI,
00:18:43
◼
►
with a few UI kit hooks here and there
00:18:45
◼
►
where I have to go into a low-level thing
00:18:48
◼
►
to hook into a system something or things like that.
00:18:50
◼
►
But the main structure of the app, everything like that,
00:18:52
◼
►
is SwiftUI, is when I first started building in SwiftUI,
00:18:59
◼
►
I was building a UI kit app in SwiftUI.
00:19:02
◼
►
And as a result, I hit lots of walls
00:19:07
◼
►
and felt like I was constantly bumping into the edges,
00:19:10
◼
►
that I kept saying, oh, this is how I would do it,
00:19:12
◼
►
or this is how I would structure my code,
00:19:14
◼
►
or this is what it would look like in UI kit.
00:19:17
◼
►
How do I do that in SwiftUI?
00:19:20
◼
►
And in a weird way, the image that comes into my mind
00:19:26
◼
►
is to think of water flowing down a hill, where
00:19:30
◼
►
when the water flows down a hill,
00:19:32
◼
►
it will encounter resistance.
00:19:33
◼
►
It'll smash into a rock or run into a bank or something.
00:19:38
◼
►
And all it does is it just gently turns and follows
00:19:42
◼
►
to the side and will just keep finding the easy path until it
00:19:46
◼
►
gets all the way to the bottom.
00:19:48
◼
►
And I think once I-- it was a bit zen to say,
00:19:51
◼
►
but once my SwiftUI development became
00:19:54
◼
►
flowing like water down a hill, everything got a lot easier.
00:19:58
◼
►
Where if I start doing counter-resistance,
00:20:00
◼
►
I think to my-- rather than like, ooh, this is SwiftUI
00:20:02
◼
►
being annoying and getting in my way, I sort of think, huh,
00:20:06
◼
►
am I doing this the way that I should?
00:20:09
◼
►
Is this a symptom of me not using SwiftUI in the way
00:20:12
◼
►
it is best used?
00:20:14
◼
►
And most often, that was the case.
00:20:16
◼
►
How could I change it to flow with SwiftUI in the way
00:20:19
◼
►
that it's expecting and get back into its path?
00:20:21
◼
►
And as soon as-- very few times in the development
00:20:25
◼
►
of Widgetsmith, which is a very complicated, large app
00:20:28
◼
►
with all kinds of features and a very wide user base,
00:20:31
◼
►
there was a solution that was more SwiftUI-ish and got me
00:20:35
◼
►
to where I wanted to go.
00:20:36
◼
►
And sometimes that means that feature doesn't quite
00:20:38
◼
►
look the way that it could on UIKit
00:20:40
◼
►
or the way that I may have initially imagined it to look.
00:20:45
◼
►
But I can get to a place that is reasonable, that is workable,
00:20:49
◼
►
that very often is very clean from a code perspective
00:20:52
◼
►
and ends up being really good.
00:20:54
◼
►
Like, I'm a huge fan of SwiftUI.
00:20:56
◼
►
And now when I go back and have to do some work in UIKit,
00:20:59
◼
►
I just like, I don't even know what I'm doing.
00:21:00
◼
►
I feel like I'm coding with oven mitts on.
00:21:02
◼
►
And so that transition is difficult and not something
00:21:06
◼
►
that is right away.
00:21:07
◼
►
But it was certainly something that I found that--
00:21:10
◼
►
and especially having the freedom to be all SwiftUI
00:21:12
◼
►
rather than cobbling something together where you're like,
00:21:15
◼
►
oh, I'm going to replace just this TableView cell in SwiftUI,
00:21:18
◼
►
or I'm just going to sort of start shimming things in here
00:21:20
◼
►
and there, made it really hard to get full SwiftUI
00:21:24
◼
►
and get all of the benefits and all of the velocity
00:21:27
◼
►
that that enables.
00:21:30
◼
►
And if you-- and so without that velocity, then what's the point?
00:21:34
◼
►
Just stick with what you have and just hope
00:21:38
◼
►
that that lasts for long enough that you can--
00:21:42
◼
►
at some point, you will stop needing to maintain Overcast,
00:21:45
◼
►
whatever that is, in 10 years, 15 years,
00:21:47
◼
►
and just ride it into the ground.
00:21:49
◼
►
But otherwise, to modernize it, you really
00:21:52
◼
►
have to just sort of embrace that future in that way.
00:21:55
◼
►
Yeah, that's a good way to look at it.
00:21:57
◼
►
I mean, you mentioned all the shimming and everything
00:21:59
◼
►
if you try to do a piecemeal approach.
00:22:01
◼
►
And I've been running into that all the time.
00:22:03
◼
►
I mean, when I was doing my first phase
00:22:08
◼
►
of my big redesign over the last six months
00:22:11
◼
►
or whatever it was-- oh, more than that.
00:22:12
◼
►
Geez, almost a year.
00:22:14
◼
►
When I was doing that, I made the decision--
00:22:16
◼
►
I talked about it on the show-- that things that were already
00:22:19
◼
►
Objective-C-- like if I was working within a view
00:22:21
◼
►
controller, if that view controller was already
00:22:23
◼
►
Objective-C, I wasn't going to rewrite it in Swift.
00:22:26
◼
►
I did a lot of that work in Objective-C.
00:22:27
◼
►
And that actually held me back a lot,
00:22:30
◼
►
and it made certain things harder, as many of the APIs
00:22:33
◼
►
are decreasingly designed for Objective-C.
00:22:36
◼
►
And I actually-- I think that was the wrong decision
00:22:40
◼
►
in retrospect.
00:22:41
◼
►
While it brought the design forward,
00:22:43
◼
►
it didn't bring any of the code forward.
00:22:45
◼
►
And it didn't decrease my technical debt in this way.
00:22:49
◼
►
It actually increased it, if anything.
00:22:51
◼
►
And it made certain parts of the iteration process,
00:22:53
◼
►
which is most of what design is, most of its iteration.
00:22:56
◼
►
It doesn't take me six months to write a few theme changes
00:22:59
◼
►
to a view controller.
00:23:00
◼
►
It takes me six months to try all the different things I
00:23:02
◼
►
have in mind and see what works.
00:23:03
◼
►
If I was going to do more of this design work, which
00:23:06
◼
►
is what I'm trying to tackle now,
00:23:07
◼
►
with the Now Playing screen and the podcast screen,
00:23:09
◼
►
I am not going to make that same choice that way.
00:23:11
◼
►
Now, I want to rewrite those screens completely.
00:23:15
◼
►
And another major thing-- my app has not yet
00:23:18
◼
►
used the new Swift async stuff yet.
00:23:20
◼
►
And I actually just had to add that to this CloudKit code,
00:23:24
◼
►
because they deprecated some of the old CloudKit methods
00:23:28
◼
►
And so I had to start using that.
00:23:29
◼
►
And that's another thing, where if your app is not
00:23:31
◼
►
made with all the async stuff in mind,
00:23:33
◼
►
that's another huge migration that, over time,
00:23:36
◼
►
needs to happen.
00:23:37
◼
►
My current thinking is that leaving things that were
00:23:41
◼
►
already the old way-- Objective-C, UI Kit--
00:23:44
◼
►
leaving things that way, if they already were, was a mistake.
00:23:48
◼
►
I now regret that.
00:23:49
◼
►
And I now think that I want to do any future work
00:23:54
◼
►
in this clean start kind of way.
00:23:57
◼
►
And that's going to take a long time.
00:23:59
◼
►
But I think you're right, though,
00:24:00
◼
►
that the app overall, the UI and everything, is very stable.
00:24:04
◼
►
And I don't really need to rush to do something quickly
00:24:10
◼
►
I should probably be taking the time to do it right
00:24:13
◼
►
and to pay down this technical debt in a way that
00:24:16
◼
►
will allow me to work better in the future,
00:24:20
◼
►
even if that means basically a rewrite of most of the UI.
00:24:24
◼
►
And I think, too, the end result of that
00:24:26
◼
►
is that it is a wonderful thing in the current environment
00:24:31
◼
►
as an iOS developer to be an expert at Swift and SwiftUI.
00:24:36
◼
►
That is the skill set that, going forward,
00:24:40
◼
►
is going to be clearly-- that's where the energy is going
00:24:44
◼
►
from Apple's perspective.
00:24:45
◼
►
That's where, as a community, things are going.
00:24:47
◼
►
And the quicker you can get yourself
00:24:51
◼
►
into that place, where you can code in SwiftUI just as well
00:24:55
◼
►
as you used to be able-- as you could in UI Kit--
00:24:57
◼
►
it's setting yourself up for opportunity and success
00:25:00
◼
►
in the future.
00:25:01
◼
►
And I worry that if you take the approach of doing it
00:25:05
◼
►
more piecemeal and trying to carry around the old code
00:25:08
◼
►
and doing it as you go, is you're never
00:25:11
◼
►
going to be able to be free of the past,
00:25:14
◼
►
such that you're going to be able to really embrace
00:25:16
◼
►
the future and to be able to really build things in the way
00:25:20
◼
►
that, at some point, you're going to have
00:25:23
◼
►
an idea for another app, inevitably.
00:25:25
◼
►
I mean, that's just-- if you're anything like me,
00:25:27
◼
►
and I think you've built a couple things over the years.
00:25:30
◼
►
So those ideas will come.
00:25:32
◼
►
And SwiftUI is great for rapid prototyping,
00:25:35
◼
►
for quickly exploring ideas, or even
00:25:37
◼
►
if you have an idea for a new feature in Overcast.
00:25:41
◼
►
And it's like, you decide you're going to add a stats area
00:25:44
◼
►
to show people their listening history over time, say.
00:25:47
◼
►
And you want to use Swift charts for this,
00:25:50
◼
►
or whatever that might be.
00:25:52
◼
►
The farther the app is in that direction
00:25:55
◼
►
to accept those new ideas, I think,
00:25:57
◼
►
will just allow you to be in this fresh space.
00:26:01
◼
►
And I think that's why I was initially thinking of nudging
00:26:06
◼
►
you in this direction and encouraging you to avoid--
00:26:10
◼
►
feeling the weight of--
00:26:12
◼
►
carrying around all this technical debt
00:26:14
◼
►
and having it feel like weight, rather than just saying,
00:26:16
◼
►
you know what?
00:26:17
◼
►
The code is fine.
00:26:18
◼
►
It works great.
00:26:19
◼
►
I'm going to partition it here.
00:26:20
◼
►
I'm going to start this new thing.
00:26:22
◼
►
I know you know exactly what you're building in terms of it's
00:26:24
◼
►
not an exploration, so you're not
00:26:26
◼
►
going to waste a lot of time there.
00:26:27
◼
►
And I would be very surprised if you just sort of sat down
00:26:30
◼
►
and worked diligently on it, that if you weren't able to
00:26:32
◼
►
build the vast majority of Overcast,
00:26:35
◼
►
again, much more quickly, in a matter of a few weeks,
00:26:38
◼
►
that you could have a basically working, rebuilt version of it.
00:26:42
◼
►
And then obviously, the actual refinement of that
00:26:45
◼
►
and filling it out will take some extra time.
00:26:47
◼
►
But at least spending that initial time to say,
00:26:49
◼
►
I'm going to rebuild the now playing screen in SwiftUI,
00:26:53
◼
►
and seeing how long that takes, and seeing
00:26:55
◼
►
what that looks like as a clean rewrite, I think
00:26:57
◼
►
would be a really instructive time, and certainly something
00:27:00
◼
►
that would be well spent to see where that goes.
00:27:03
◼
►
And if it does work, then great.
00:27:05
◼
►
And it's just like, the now playing screen,
00:27:06
◼
►
if you're on, whatever, an iOS 16,
00:27:08
◼
►
is just different than the old one.
00:27:09
◼
►
And that's fine.
00:27:10
◼
►
And that works great.
00:27:11
◼
►
And I don't think anyone would notice, or if they did,
00:27:14
◼
►
it would hopefully be noticing it in a positive sense.
00:27:17
◼
►
It's funny you mention that, because that's literally
00:27:19
◼
►
what I tried to do over the last few days,
00:27:21
◼
►
was the now playing screen.
00:27:23
◼
►
And that was my first thought.
00:27:25
◼
►
Oh, let me do this in SwiftUI.
00:27:26
◼
►
However, I ran into a wall immediately,
00:27:29
◼
►
which is that the now playing screen, the same view
00:27:32
◼
►
controller is operating both when
00:27:35
◼
►
it is minimized to the toolbar and when it is fully expanded.
00:27:38
◼
►
It's the same view controller.
00:27:39
◼
►
It's the same views that shrink down and join
00:27:42
◼
►
their new positions down below.
00:27:45
◼
►
And it's an interactive transition.
00:27:47
◼
►
And so I could not for the life of me
00:27:50
◼
►
figure out how to do that without everything else being
00:27:53
◼
►
SwiftUI around it.
00:27:55
◼
►
That's when I started getting into, oh, let me try SwiftUI
00:27:56
◼
►
navigation stuff.
00:27:57
◼
►
It's new in iOS 16.
00:27:59
◼
►
And I just slammed into so many walls doing that,
00:28:03
◼
►
and what seemed like bugs and limitations.
00:28:06
◼
►
And I just couldn't break through.
00:28:09
◼
►
I couldn't make it happen.
00:28:10
◼
►
And so I just gave up.
00:28:12
◼
►
And I was just going to go for a dog walk
00:28:14
◼
►
and have dinner with my family and think about what
00:28:16
◼
►
I'm doing with my life.
00:28:19
◼
►
But maybe it didn't have to be that way.
00:28:21
◼
►
I mean, I don't know.
00:28:22
◼
►
I'm sure there's a way to do this piecemeal.
00:28:24
◼
►
But I think it's going to be much easier
00:28:26
◼
►
to do it all at once.
00:28:27
◼
►
Yeah, exactly.
00:28:29
◼
►
And I think you're going to encounter
00:28:30
◼
►
so many of those things get easier when it's all one
00:28:33
◼
►
or it's all the other.
00:28:34
◼
►
And if you're only dropping down to UI Kit
00:28:37
◼
►
when you absolutely have to, I think
00:28:39
◼
►
we'll go a long way to making this work.
00:28:42
◼
►
And the reality is if in the end you decide you don't like it
00:28:45
◼
►
and you go down this road for a couple of weeks
00:28:49
◼
►
and you decide, you know what, this isn't for me,
00:28:52
◼
►
then you've gotten several weeks of experience
00:28:55
◼
►
doing SwiftUI work, which is making you a better SwiftUI
00:28:57
◼
►
developer, which is definitely helpful.
00:28:59
◼
►
And you're no worse off.
00:29:00
◼
►
You can go back and sort of think about it
00:29:02
◼
►
and take a different approach later.
00:29:03
◼
►
Because the nice thing about a hard fork
00:29:05
◼
►
is you're not breaking the old version in the process.
00:29:08
◼
►
You're just completely clean and separate.
00:29:09
◼
►
And it's a nice, straightforward path forward as a result.
00:29:14
◼
►
Thanks for listening, everybody.
00:29:16
◼
►
And we'll talk to you in two weeks.