Under the Radar

203: Modernizing Overcast


00:00:00   Welcome to Under the Radar, a show about independent iOS app development.

00:00:04   I'm Marco Arment.

00:00:05   And I'm David Smith. Under the Radar is never longer than 30 minutes, so let's get started.

00:00:09   So I am riding a lot of Swift finally.

00:00:13   I know, it only took what, six years, five years?

00:00:17   Many years, I don't know.

00:00:19   Probably, like, early on it was fine to wait.

00:00:22   I think it's probably been at least two years too late that I've jumped in at this point.

00:00:26   There was a window when it was like, you know, I think it's appropriate to be cautious about this new technology.

00:00:32   Like, especially in those early years where code compatibility was not something that was required.

00:00:37   I mean, the ABI wasn't even stable for a while.

00:00:40   Right.

00:00:41   But I feel like we're well past that at this point.

00:00:44   Yeah.

00:00:45   Yeah, like, I very much am happy I wasn't a Swift beta tester, basically.

00:00:49   Because that requires you to be a certain level of enthusiast and language nerd that I am not.

00:00:54   And with a certain level of patience that I don't have.

00:00:57   And so I've waited until it is very, very stable and not changing very much anymore.

00:01:04   And that's when I jumped in. And I feel good about that.

00:01:07   And one of the reasons why I did that is because I decided this past few weeks,

00:01:16   the HomePod mini was announced and with it a whole bunch of updates to what HomePods can do.

00:01:23   The HomePod mini is a very attractive price.

00:01:26   And while nobody has them yet, I have a feeling it's probably going to succeed as a general device.

00:01:31   And they're probably going to sell a good number of them.

00:01:33   And so I was curious to really make sure that Overcast can be good on the HomePod.

00:01:41   And I already did AirPlay 2 last year.

00:01:45   And it was a massive job and in retrospect possibly not worth it.

00:01:49   But it was a big deal and I eventually got there and it was fine.

00:01:53   But I didn't have good Siri intent support.

00:01:57   Or I don't know what to call this. Is it intense?

00:02:00   It used to be a one-time called Shortcuts, then Siri Shortcuts, then Intents, and now just Siri integration?

00:02:08   It sort of makes me think of NSUserActivity.

00:02:12   It's one of these things where there's technological aspects to it that are different.

00:02:18   Like you use Intents to configure your widgets, which has nothing to do with Siri at all.

00:02:24   But I think the thing you're talking about is being able to say, "Excuse me, lady in the dome."

00:02:32   I don't know. "In the snowball. Excuse me, snowball. Would you play the latest episode of ATP in Overcast?"

00:02:39   That's what you're after, right?

00:02:41   The ability to ask the snowball to play something.

00:02:45   I think that's Siri Shortcuts, I think.

00:02:49   Yeah, or it at least uses Intents and it uses the Play Media intent and everything.

00:02:53   So anyway, Overcast has supported Intents since they came out for, I believe it was iOS 12.

00:02:58   It was either 11 or 12. I forgot one of those.

00:03:01   And when I wrote that first version of it, this is when Shortcuts launched and with the API and everything,

00:03:07   it was pretty rough to work with. It was a very clunky workflow.

00:03:11   You had this giant, weird, plist, GUI configurator in Overcast to configure your Intents.

00:03:17   And then what you had to do to get parameters and stuff was always a big pile of hacks

00:03:23   because it didn't actually support native parameterization.

00:03:25   And what you could do as a media app for play or pause, you had to do so much stuff manually and hacky.

00:03:31   And it was buggy and it didn't work well and the API was kind of miserable to work with.

00:03:36   On top of that, I was working with it from Objective-C, which you can do,

00:03:42   but it would frequently cause problems in Xcode because all those Intents from that weird plist thing

00:03:48   get automatically generated into classes that get magically imported into your project.

00:03:52   And that doesn't work a lot of times with Objective-C.

00:03:55   It'll break the build in weird ways that you'll have to clean the build folder and hope it builds the second time.

00:03:59   I mean, all those weird bugs that we had.

00:04:01   And so this was a big pile of hacks. And then when iOS 13 came out last year,

00:04:06   they added with the 13 SDK a whole bunch of improvements to this.

00:04:10   They added media Intents that could actually take parameters,

00:04:13   you could actually specify what your library of content was to the Siri API.

00:04:18   So you could say, "Here's the list of titles of playlists in my app. Here's the list of titles of podcasts.

00:04:23   My app, by the way, is a podcast app instead of a music app."

00:04:26   And you could specify all this stuff.

00:04:28   I had this old iOS 12 system that I hated that was a big pain in the butt to build.

00:04:33   And you were still doing all this stuff through the Intents extension.

00:04:38   And so in order to make this work, you had to have this data shuffling between the extension and the main app,

00:04:44   as you do with any extension.

00:04:46   And that's one thing when it's simple things like, "Tell the app this command."

00:04:51   It's a whole other thing when you have to expose your entire library of content through it

00:04:55   and have it navigate and perform searches and everything.

00:04:57   It just becomes very complicated.

00:04:59   So I kind of punted on that.

00:05:01   I had seen that not a lot of people were using the Intents I had built for iOS 11 or 12.

00:05:07   And so I thought last year when 13 came out, this isn't worth adopting yet.

00:05:11   I'll put this on the back burner.

00:05:13   I have more important things to do that more people are using right now.

00:05:16   So I kind of put it on hold.

00:05:19   So now iOS 14 comes out.

00:05:23   14 SDK introduces a major new improvement to this,

00:05:27   which is that you can now get rid of the extension and perform whatever Intents you want right in your app.

00:05:34   It'll just background launch your app.

00:05:36   That's amazing.

00:05:37   Yes! That's a huge improvement because that needs way less code.

00:05:42   But in order to do this, you have to adopt the new "scene" -- "new" in quotes -- "scene" APIs.

00:05:50   The new "new" last year.

00:05:52   Was it even that recent?

00:05:54   I think it was new last year. I'm pretty sure.

00:05:56   Anyway, so you have to adopt the "scene" APIs.

00:05:59   So much of your app delegate stuff moves into the new "scene" delegate.

00:06:04   By the way, there can be multiple "scene" delegates.

00:06:06   You better account for that and things like that.

00:06:08   And so I took this opportunity with my six-year-old app.

00:06:12   So you can imagine the app delegate of a six-year-old app.

00:06:16   It's large, is my guess.

00:06:19   Especially because it's Objective-C, so it's all one file, too.

00:06:22   Well, actually, no. I had actually split it up.

00:06:25   I had two category files that extended it.

00:06:27   I had one for notifications and one for intent handling.

00:06:30   So I had split off some functionality, but not most.

00:06:33   Most of it was one big file.

00:06:35   And the other thing motivating this was

00:06:39   I decided over the summer, you know what, this whole widget thing,

00:06:43   I don't know if it's going to be a big deal.

00:06:45   I don't think a lot of people are going to use widgets.

00:06:47   No, no one's going to use widgets.

00:06:49   It's a passing fad.

00:06:51   Yeah, well, like iMessage apps.

00:06:53   I thought, like, Apple launches all sorts of--

00:06:55   TV OS, like, Apple launches all sorts of stuff that

00:06:57   we think might be a big deal, and then it comes out and no one uses it.

00:07:00   And I'm like, OK, well, I guess, you know, oh, well, if we skipped it, great.

00:07:04   And if we didn't skip it, well, there goes a bunch of wasted effort, right?

00:07:07   So I decided, let me hold off on widgets.

00:07:10   I was using them myself during the beta period.

00:07:13   I was trying them out.

00:07:14   And I wasn't finding them incredibly useful because they were so big.

00:07:17   I didn't have space for them on my home screen and stuff.

00:07:20   So I thought, you know what, this will probably pass.

00:07:22   And, well, you, more than anybody, knows that didn't really happen.

00:07:26   And it turns out they're a big deal.

00:07:28   And I am having competitive pressure from my users.

00:07:33   And I'm actually getting one-star reviews, like, meaningfully now

00:07:38   because I don't have a widget yet.

00:07:40   That's harsh.

00:07:41   Tell me about it.

00:07:43   And so I decided, like, OK, I should probably actually do this.

00:07:47   Like, enough of my customers are wanting this.

00:07:49   I need to do this.

00:07:50   Well, widgets, as you said, also use the intent API.

00:07:55   And also, you know, our modern extensions that need some of this stuff.

00:08:00   I need to learn Swift UI.

00:08:02   I need to learn more Swift and everything.

00:08:04   So I thought, this is a great time to rewrite my app delegate,

00:08:10   to use the new scene API so I can get the Siri support with the background app stuff.

00:08:16   So I can also use all the new stuff with the HomePod integration.

00:08:19   So I can also use better Siri integration.

00:08:22   And, by the way, this would also make widgets easier.

00:08:25   And, by the way, if I separate all these things,

00:08:27   I can also make my watch app better for boring reasons

00:08:30   that won't fit in a 30-minute podcast.

00:08:32   So, and my watch app is basically on fire right now.

00:08:35   Like, it's a terrible mess.

00:08:36   Like, the syncing of episodes for offline playback on the watch

00:08:41   is completely broken for a lot of people.

00:08:44   Not everybody, but for a lot of people.

00:08:45   And I have to fix that.

00:08:47   And so there's all sorts of things that have piled up.

00:08:51   So I've decided to tackle one of the stupidest things you can do as a programmer,

00:08:56   a big rewrite.

00:08:57   Yeah.

00:08:58   But I focused it so it wasn't totally killing my business.

00:09:01   I focused it only on the app delegate, the now new scene delegate,

00:09:06   moving a whole bunch of the data and sync engine stuff

00:09:10   into a new thing called the session that is cross-compiling with watchOS.

00:09:17   So I can have the exact same data and sync layer between watchOS and iOS

00:09:21   and whatever else OS comes later.

00:09:24   So, you know, and it's so much work.

00:09:27   Just pulling out calls from the model layer that went to the app delegate for some reason.

00:09:32   Or all this weird little spaghetti that you tell yourself you're never going to do,

00:09:36   but in practice you end up doing.

00:09:37   Oh, sure.

00:09:38   I mean, that's--

00:09:39   And in-- it sounds like you're being down on yourself.

00:09:41   Like, that's the-- it is often just-- that's the path of least resistance,

00:09:46   the obvious thing.

00:09:47   And if you go too crazy separating things out from the start,

00:09:52   you end up building all this infrastructure that you may not ever actually need.

00:09:56   Like, you build the thing so that it's generic and can be used anywhere,

00:09:59   but it's actually only used in one place.

00:10:01   And so don't be too hard on yourself in terms of, like, doing that.

00:10:04   But yes, the process of unraveling that when it does come time

00:10:07   is certainly not straightforward.

00:10:09   Exactly.

00:10:10   And I also decided while I'm rewriting my six-year-old app delegate

00:10:14   and breaking up all this code, I should do the new one in Swift.

00:10:18   And so I've been finally, for the first time ever,

00:10:22   plowing ahead with Swift at full speed.

00:10:25   Not just using it piecemeal here and there,

00:10:28   but, like, all the new code I'm writing is Swift now.

00:10:32   And that's something I've never been able to say.

00:10:34   Because you'd previously used it in your Today View.

00:10:36   Am I remembering this right?

00:10:38   There was some part of your app that you used it before, but--

00:10:42   Yeah, like, I used it in a couple of extensions here and there.

00:10:44   A couple of the classes in the main app were Swift before,

00:10:47   but not many because it's a giant Objective-C app.

00:10:50   And it just made pragmatic sense most of the time

00:10:54   when I was working with other Objective-C code

00:10:56   to just write new stuff in Objective-C when it came up.

00:10:58   But now I decided I'm going to do this from the ground up.

00:11:01   And I'm not going to rewrite stuff for no reason if it works

00:11:04   and if there's no motivating SDK or competitive reason to update it.

00:11:09   But now I'm saying everything I'm doing that's new,

00:11:11   that's updated for good reasons or that is new code,

00:11:14   that's all Swift now.

00:11:16   And that's something that's brand new for me.

00:11:17   And so I took this entire--

00:11:19   the last two weeks since we last talked,

00:11:21   I have been doing tons of work just refactoring and restructuring

00:11:26   and rewriting a lot of that low-level code in the app.

00:11:29   And I finally-- I have it now.

00:11:31   It's running on my phone.

00:11:32   It seems to be fine.

00:11:34   I'm not brave enough to put it in beta yet.

00:11:36   I want to do more testing.

00:11:38   But it seems okay.

00:11:41   And it just-- and so much of the app has been touched by this.

00:11:44   Like, just-- but in ways that a user would never know.

00:11:47   Like, just would never see.

00:11:49   All this is to say I have reached a point now

00:11:52   where I have the app and scene delegate all rewritten.

00:11:55   It's all Swift.

00:11:56   I have the Siri intent support, whatever it's called.

00:11:58   I have the-- all that stuff going great.

00:12:01   So you can say, like, hey, thing, play--

00:12:04   you know, play-- and you can name any podcast,

00:12:06   whether you subscribe to it or not,

00:12:08   and you can say play that in Overcast

00:12:10   and it will play it no matter what.

00:12:12   That's great.

00:12:13   If you don't have it, it'll add it.

00:12:14   It'll perform a web search if it has to.

00:12:16   Like, all that stuff is all done.

00:12:18   You can ask for your playlist by name, of course.

00:12:21   I can say, hey, thing, play my lunch playlist.

00:12:23   And that was-- that was quite something.

00:12:25   That's great.

00:12:26   So, like, I'm making great progress there.

00:12:29   And at the same time, I have my entire session layer now

00:12:33   running on the watch for the first time.

00:12:35   Not on the real watch, in the simulator only so far,

00:12:37   but I have, like, you know, just--

00:12:39   I was able to run it, and I--

00:12:41   like, to the point where, like, you run the app,

00:12:43   I could finally get it to compile,

00:12:45   which is most of the work.

00:12:47   Yeah.

00:12:48   And so now I have the data layer running on the watch.

00:12:51   Now, it doesn't actually do anything in the UI yet

00:12:54   because the UI and the data layer

00:12:56   are not talking to each other yet.

00:12:58   So here, this is where I bring the question of the episode

00:13:02   to you.

00:13:03   Sure.

00:13:04   But first, we are sponsored this week--

00:13:07   see the transition there-- by Pingdom from SolarWinds.

00:13:12   Now, if you have a website or a web service

00:13:14   or anything that runs on the web,

00:13:16   and you have something important,

00:13:18   like a shopping cart if you're a store site,

00:13:20   registration forms if you're a service,

00:13:22   contact pages, or if you just have a web API

00:13:25   that you need to monitor,

00:13:27   if you answered yes to any of that, you need Pingdom.

00:13:30   Nobody wants their critical website transactions

00:13:33   or their web service backend to fail

00:13:35   because that means not only a bad experience for users,

00:13:38   but it also could mean lost business for you.

00:13:41   So you can set up monitoring with Pingdom.

00:13:44   And this can be very simple monitoring

00:13:46   from just check if this web page is up

00:13:48   and make sure it includes this phrase.

00:13:50   So you can design certain things around that

00:13:52   or you can tell when a page changes.

00:13:54   But you can also do transaction monitoring.

00:13:56   This can alert you when things like cart checkouts

00:13:58   and forms and login pages fail

00:14:01   before they affect your customers and your business.

00:14:04   You will know from Pingdom the moment any of them fail

00:14:07   in whatever way you want to be notified.

00:14:09   They have customizable notifications.

00:14:11   You can customize how you're alerted,

00:14:13   who is alerted, how bad it is,

00:14:15   like how severe the outage has to be.

00:14:17   It is great. I've personally been a Pingdom customer

00:14:20   for, oh geez, eight to ten years.

00:14:23   I used it since the beginning of Overcast for sure.

00:14:26   I used it in this paper before that.

00:14:27   I even used it on marker.org.

00:14:28   It's great.

00:14:29   And Pingdom is a great monitoring service.

00:14:32   I can say that honestly. It's fantastic.

00:14:34   So if you want to see, you want to monitor your stuff,

00:14:36   go to Pingdom.com/RelayFM right now

00:14:40   for a 14-day free trial with no credit card required.

00:14:44   When you sign up, use code RADAR at checkout

00:14:47   to get a huge 30% off your first invoice.

00:14:50   So RADAR at checkout to get 30% off your first invoice

00:14:53   at Pingdom.

00:14:54   Thanks to Pingdom from SolarWinds

00:14:56   for their support of this show and RelayFM.

00:14:59   So the question of the hour, half hour,

00:15:02   is I have now gotten to the point where I have

00:15:06   all this restructuring in my main app.

00:15:08   I have the huge data layer transition running on my watch app.

00:15:12   But my watch app, which admittedly is not that big,

00:15:15   it's maybe a few hundred lines of code,

00:15:17   is an entirely Objective-C app,

00:15:21   although I just rewrote the app,

00:15:23   the extension delegate in Swift as part of this move.

00:15:26   So it's a mostly Objective-C app.

00:15:28   The entire UI layer is Objective-C.

00:15:30   And it's all based on this old transfer system

00:15:34   with the phone that I'm abandoning.

00:15:36   And I have this new data layer below it all.

00:15:39   So I have a lot of work ahead of me

00:15:41   to either adapt the UI code to the new data layer code

00:15:46   or rewrite the entire UI code in Swift

00:15:50   and possibly also in Swift UI.

00:15:53   So what do you think I should do about the UI code

00:15:56   in my watch app?

00:15:58   Sure. Okay.

00:16:00   Well, first thing, great job on all the progress thus far.

00:16:04   That is no small thing.

00:16:06   And especially I know from many experiences

00:16:10   that first feeling when it all kind of seems to work

00:16:13   and you're almost a little concerned that it seems to work.

00:16:16   It's this eerie feeling of like, "Huh, nothing's broken.

00:16:20   Everything's running. Seems fine."

00:16:23   Yeah, it makes you suspicious of like,

00:16:25   "I had to have broken something.

00:16:27   If it isn't something obvious, how am I ever going to find it?"

00:16:29   It's like, I almost feel it's better

00:16:31   when it's just obviously broken,

00:16:32   because then it's like, it's clear.

00:16:34   There's not this lurking fear of a subtle bug out there

00:16:37   just waiting to pounce on you.

00:16:39   Yeah, it's like, "There's going to be some feature

00:16:41   I never use that I broke somehow.

00:16:43   I'm never going to know it,

00:16:44   and the beta testers won't find it."

00:16:46   And the thing is, the nice thing is

00:16:48   you have a large enough beta audience, I think,

00:16:50   that it's unlikely that it's going to...

00:16:54   No big issue should likely survive

00:16:57   the amount of beta testing that I think you're able to

00:16:59   sort of leverage on something like this,

00:17:01   especially with the breadth of that.

00:17:03   So hopefully that'll be fine.

00:17:04   You'd be surprised.

00:17:05   I mean, I'm sure things get through,

00:17:07   but there's always hope.

00:17:09   But in terms of the watch, I think

00:17:11   the things that come to mind is like,

00:17:14   the first question is,

00:17:16   "What version of watchOS do you expect to require going forward?"

00:17:20   Oh, I forgot to mention that.

00:17:21   So I looked at my stats, and I said recently that

00:17:25   I wanted to keep compatibility with 12 and 13

00:17:28   because it was just pragmatic to do so.

00:17:31   And I was looking at my stats,

00:17:32   and I decided as part of this big move,

00:17:34   it made a lot of things easier

00:17:36   not to go to 14,

00:17:37   because that's too aggressive for me right now,

00:17:38   but I went to 13 and watchOS 6.

00:17:41   Okay.

00:17:42   Because that made a lot of...

00:17:44   watchOS 6 was an even easier decision.

00:17:47   iOS 13, according to my stats,

00:17:49   I'm only losing from the 12 people.

00:17:51   I'm losing like 3.5% now.

00:17:54   The adoption of 14 has been very high,

00:17:56   and now that it's new iPhone season,

00:17:58   I expect that to go even higher.

00:18:00   So, and this release of the app

00:18:02   is probably at least a month or two out.

00:18:04   Just because it's so much work,

00:18:06   I'm trying to do a lot at once,

00:18:07   so it's probably about a month out,

00:18:08   if I had to guess.

00:18:09   But, so, you know, I went with 13

00:18:12   because I was only losing like 3.5% of people

00:18:16   by ending 12 compatibility.

00:18:18   And watchOS 6, I'm losing like

00:18:21   less than 1% of people that were on watchOS 5 still.

00:18:24   So the watchOS 6 requirement

00:18:26   was actually a no-brainer.

00:18:27   And that actually helps a lot with,

00:18:29   with what I can do with the audio layer as well there.

00:18:33   So that's why I moved to that.

00:18:35   - Yeah, 'cause I think if you can require watchOS 6,

00:18:39   it feels like a good time

00:18:43   to adopt SwiftUI on the watch.

00:18:47   - Ooh, I was hoping you'd say that.

00:18:49   I'm a little scared.

00:18:50   - Sure, 'cause...

00:18:51   - 'Cause I have to rewrite a lot of my UI code anyway.

00:18:53   - Sure.

00:18:54   But, I gotta, I mean, it's been a while

00:18:57   since I used all of the parts of the overcast watchUI.

00:19:01   But from what I remember, it's like,

00:19:03   we're talking about like three or four screens, maybe?

00:19:06   - It's a very small app, like UI-wise,

00:19:09   and it's not very good.

00:19:10   I'm willing to entertain changes.

00:19:12   - Sure.

00:19:13   'Cause I feel like it's,

00:19:15   you're gonna have to, if you're gonna

00:19:18   like need to essentially build hooks

00:19:20   from your new common data layer,

00:19:22   into a UI framework.

00:19:24   Like that work is gonna have to happen no matter what,

00:19:28   because your existing UI and the new data layer

00:19:32   aren't compatible with each other anyway.

00:19:34   So, it's like if you have to do that effort,

00:19:36   like doing it with SwiftUI, I think is gonna be

00:19:39   a great place to, like that work is not gonna be

00:19:43   for nothing, because that work is going to ultimately

00:19:46   allow you to, when you get to working on your widgets,

00:19:49   they're gonna have to do exactly the same integration.

00:19:51   There may come a point where you need to do SwiftUI work

00:19:54   with your main app, and that work is not gonna be

00:19:56   wasted there, and so it feels like it's a good thing

00:19:58   in terms of, and this is something that,

00:20:00   it's relatively straightforward, it's just a bit kind of,

00:20:03   you just have to have a different mindset within SwiftUI

00:20:06   where you're just taking your data layer

00:20:08   and making it so that it's all sort of this

00:20:10   combined observable object stuff,

00:20:13   is the primary aspect of what you're gonna have to do.

00:20:16   Whereas SwiftUI is very, you know,

00:20:19   your data layer sort of just tells the UI something's changed

00:20:23   and then the UI will come and pull the new data out

00:20:27   of the data model and so on, and so you just have to

00:20:30   kind of build that in, it's just a slightly different format

00:20:32   than what you would typically do where, you know,

00:20:35   the data layer is a bit more, like, I don't know,

00:20:39   it's imperative rather than declarative programming,

00:20:42   but whatever, you're gonna have to do that work

00:20:44   no matter what, and I think having now built

00:20:48   a tremendous, I've built a lot of watch apps,

00:20:50   and what is possible and what is easy

00:20:55   in SwiftUI on watchOS makes it so that,

00:21:00   like, I don't ever want to touch a watch kit

00:21:03   sort of watch app again, because there's so many things

00:21:06   that are just, you run into this place where

00:21:09   you want to do something, you have an idea,

00:21:11   you have a vision for how you want to build it,

00:21:13   and with watch kit you will hit this point

00:21:16   where suddenly it's just impossible.

00:21:19   It isn't like, oh, it's difficult, or, oh,

00:21:21   it's, like, challenging to do, it's like, no,

00:21:23   it's just, that's not possible, that's not the way

00:21:25   watch kit works, and that gets really frustrating,

00:21:28   and it could be, like, simple things like,

00:21:30   say you wanted to reorder a playlist on your watch,

00:21:35   so you have, like, a list of shows, a list of episodes,

00:21:38   and you wanted to move them around.

00:21:40   In SwiftUI, super straightforward on the watch.

00:21:43   In watch kit, impossible.

00:21:46   Like, the only way you can do it is, like,

00:21:48   you'd have to, like, put arrows, like, up arrow,

00:21:50   down arrow on each row or something,

00:21:52   and you, like, tap the arrow, and then it, like,

00:21:54   would swap with the one above it or something,

00:21:56   whereas in SwiftUI you just give, add, like,

00:21:58   add a modifier to a list, and then it just, like,

00:22:02   you get automatic, like, free drag and drop,

00:22:04   and it's, like, things like that are just so much better

00:22:07   that I think at this point, spending any amount of time

00:22:10   on watch kit, unless it was essentially done,

00:22:14   and it was, like, oh, it'll be, like, half a day of work,

00:22:17   and then the watch app's updated,

00:22:19   and I can start using it, like, great, go ahead and do it,

00:22:22   but if it's gonna be any amount of work,

00:22:24   then I feel like that's the place to do it,

00:22:26   and I think it's also, the watch, and I think this is also

00:22:29   from my experience where I built, so I built,

00:22:32   with WatchSmith, I built, the iOS app was in UI kit,

00:22:36   but the watch app was in SwiftUI,

00:22:38   and I learned SwiftUI essentially building that watch app,

00:22:41   and then I came to build Widgetsmith,

00:22:43   Widgetsmith is entirely written in SwiftUI,

00:22:45   so I built the, I essentially re-implemented

00:22:48   the Y kit interface that I had built for WatchSmith

00:22:52   in SwiftUI for Widgetsmith,

00:22:54   and I did that because it just, once I've kind of

00:22:59   flipped that switch in my brain, it became so much more fluid

00:23:02   and so much more productive for me to sort of just stay

00:23:06   in the SwiftUI mindset, and so I think I can say

00:23:09   that a watch is a great place to learn SwiftUI

00:23:12   because the screens are so much smaller,

00:23:15   the interactivity is so much simpler,

00:23:18   and it's like a very constrained problem,

00:23:21   and it also gives you just more capability,

00:23:24   and so in general, that's sort of the direction

00:23:26   that I think would be worth doing,

00:23:28   and I think it's also, like, in the context

00:23:30   of this broader kind of rewrite of what you're doing,

00:23:32   like, going, that is clearly, like, there is no work

00:23:36   getting done on WatchKit anymore, I'm sure.

00:23:39   Like, that is a sort of, if you run into any bugs,

00:23:41   if you run into any issues, if weird things start happening,

00:23:44   like, that is not a place that you're going to get a lot of,

00:23:46   you know, expect that in WatchOS, you know, 7.2.6,

00:23:50   they're going to be fixing this weird, esoteric WatchKit bug.

00:23:53   Like, that's not going to happen in SwiftUI bugs.

00:23:55   Very, there's lots of bugs being fixed there.

00:23:58   It seems much more reliable, so, like, my instinct

00:24:01   is that's your best bet.

00:24:03   It's just sort of, just keep this train rolling,

00:24:06   and just keep, you know, just, like, you've torn up

00:24:09   and rebuilt a bunch of stuff, it's like, just keep going,

00:24:12   and, you know, rebuild and just sort of make your Watch app

00:24:16   what it could actually really be, with, like, a real UI

00:24:19   that isn't WatchKit, which is not a real UI.

00:24:22   - Yeah, agreed.

00:24:24   And I'm going to be the first person to be, you know,

00:24:27   dancing on the grave of WatchKit when I finally destroy it,

00:24:30   but, like, I did hesitate, because I'm like, you know,

00:24:33   the main problem with my Watch app, you know,

00:24:35   the UI is not great, but the main problem with the Watch app

00:24:38   is not the UI, and so pragmatically, I was thinking,

00:24:41   I should probably just fix the data layer and the transfer layer

00:24:45   as much as possible, and then I can just easily adopt

00:24:48   the UI to it, but when I look at, like, you know,

00:24:51   what that actually is, and I think you're right,

00:24:53   that, like, you know, my use case here is probably going to be

00:24:55   a pretty straightforward SwiftUI app.

00:24:58   I think it does make more sense, you know, because I have to do

00:25:01   a lot of work anyway to adapt the UI in some form.

00:25:06   If I'm going to do a lot of work, I might as well do a lot of work

00:25:09   that has a bigger payoff than just adopting my old UI,

00:25:12   which isn't that great, you know.

00:25:14   - And the biggest payoff, I think, is, like,

00:25:17   personal development-wise, like, I think it is a,

00:25:20   you will be in a much better place, because clearly SwiftUI

00:25:23   is the direction that Apple is heading.

00:25:25   It is clearly the platform that they're putting the most

00:25:28   energy and effort behind internally for the cross-platform,

00:25:32   like, all of their, you know, the directions they're heading

00:25:36   seem to be SwiftUI-driven, and so it's going to be a much

00:25:41   better place to get comfortable in a relatively constrained

00:25:45   problem before you kind of, you don't end up in the same

00:25:48   situation with Swift, right, where it's like,

00:25:50   there was definitely, SwiftUI was not the right time

00:25:53   to use it to adopt SwiftUI last year.

00:25:55   As someone who did adopt it last year,

00:25:57   I can tell you that definitively.

00:25:59   It was definitely too early, it did not work well,

00:26:02   there was a lot of weird debugging and Xcode issues.

00:26:05   I would say now, though, it feels like it's sort of

00:26:08   crossing over that point, and, like, if you,

00:26:11   if this was, it's like, if you didn't need to do a UI rewrite,

00:26:15   I may not necessarily, like, it wouldn't be as required,

00:26:19   but I think if you're having to do anything in there,

00:26:21   it's past that point where it's painful,

00:26:24   now it's just a new tool that, you know, sometimes has some

00:26:27   weird edge cases, and there's a few things we,

00:26:29   you know, I wish it did differently, but overall it seems to

00:26:31   work much more reliably, and the tooling for it is so much

00:26:35   better, and even just getting experience using the new SwiftUI,

00:26:39   like, interactive development thing, where you can, you know,

00:26:42   have a live updating example of your app while you're making it,

00:26:46   like, getting used to that development, I found, is very,

00:26:49   very potent in terms of, from a speed of sort of prototyping

00:26:53   and development perspective, so I think, I'm going to recommend

00:26:58   that you give it a try at least, and I think the reality too is

00:27:01   give it a try, and it's like, if it, if like, after a day or two,

00:27:04   you're like, this is, this is a terrible idea, then that's fine,

00:27:07   like, you can go back to it, watch it, it's going to be waiting

00:27:09   for you there, but I think it's worth giving it a try at this point,

00:27:12   especially in the context of all the other work you're doing.

00:27:15   So one more question, and that is, should I, you know, SwiftUI,

00:27:20   it's 1.0, it's WatchOS 6. Should I wait until I can require

00:27:25   WatchOS 7 before shipping this update? Like, is the SwiftUI

00:27:30   difference between 6 and 7 big? Because, like, one thing I really

00:27:35   don't want to do is have to test a lot on WatchOS 6, and have to

00:27:38   support, like, you know, ancient SwiftUI 1.0-isms, I know ancient

00:27:41   from last year, and, because right now I'm already at 75% WatchOS 7.

00:27:46   So I think the biggest things that you would have to watch out for,

00:27:51   you would have to deal with anyway, because the biggest things that

00:27:55   are kind of WatchOS 6 to WatchOS 7 differences are the removal of

00:28:00   Force Touch, and the context menu system in WatchOS, and so

00:28:06   whatever you do, you're going to have to make sure you're not

00:28:09   using that anywhere, because in order for it to work on WatchOS 7,

00:28:12   you have to get rid of it. And that's, even if you stay on WatchKit,

00:28:16   or 6 or 7, doesn't really matter. And then the other thing is the

00:28:20   way that the complication system works is very different in 7,

00:28:25   but the old system, I think, still can work, and I don't think your

00:28:29   complications are going to be complicated enough that it would

00:28:32   actually matter.

00:28:33   - No, I literally don't do anything. I just have a launch complication.

00:28:35   It's my app icon, that's it.

00:28:37   - Yeah, so then I don't think it would actually be that difficult,

00:28:40   because the changes in SwiftUI itself, most of them are sort of

00:28:45   backwards compatible in a way that they were Swift language changes,

00:28:49   rather than being OS changes. And so there's some changes to

00:28:54   when you have to call self, and when you have to, like some of the

00:28:57   language semantics, but I believe all of those kind of work fine

00:29:01   on the old version. They just, because the API didn't change,

00:29:05   it's just some of the Swift language stuff changed. So I think you'd be fine

00:29:08   with requiring, you don't need to wait for 7, if you can, that's awesome,

00:29:12   but if you don't, I think you'd be fine with 6 and 7 working together.

00:29:15   - Oh, great. Well, thank you very much, this actually helps a lot.

00:29:19   - There you go.

00:29:20   - Now you've given me a lot of work for the next two weeks, but...

00:29:22   - Hey, you know, that's what I'm here for. Keep you busy.

00:29:25   - Yep. Alright, thank you everybody for listening, and we'll talk to you in two weeks.

00:29:29   - Bye.

00:29:31   [BLANK_AUDIO]