PodSearch

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]