PodSearch

Under the Radar

183: Compatibility Contrast

 

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.

00:00:06 ◼   ► Under the Radar is never longer than 30 minutes, so let's get started.

00:00:09 ◼   ► I'm having one of those amazingly productive few day spans.

00:00:14 ◼   ► These don't come around often.

00:00:16 ◼   ► Wait, we should stop recording.

00:00:18 ◼   ► You just go back to working and we'll just pick this up later,

00:00:21 ◼   ► whenever you get nonproductive again.

00:00:25 ◼   ► Come back to the podcast when I'm lazy as heck.

00:00:28 ◼   ► There you go.

00:00:30 ◼   ► So I've been doing a quick bit of follow up.

00:00:32 ◼   ► The last episode I discussed, or the one before that, whatever it was,

00:00:36 ◼   ► discussed basically my decision to re-add iOS 12 support back to Overcast

00:00:42 ◼   ► because I was basically getting kind of killed in the app store for not having it

00:00:46 ◼   ► and adoption of 13 seemed slower than I expected.

00:00:50 ◼   ► And I kind of decided, you know what, let me see what it would take

00:00:54 ◼   ► to re-adopt iOS 12 and re-support it.

00:00:57 ◼   ► And so I now have the results of that experiment.

00:01:00 ◼   ► It's not in the store yet, but re-adopting iOS 12 took me about a half a day.

00:01:07 ◼   ► That's not very long.

00:01:09 ◼   ► No, and it was -- I kind of feel bad.

00:01:14 ◼   ► Like, had I known it would be that easy,

00:01:17 ◼   ► I probably wouldn't have dropped support for it in the first place.

00:01:20 ◼   ► Sure.

00:01:21 ◼   ► But it's just like the very first thing I do every summer, or at least that I have done,

00:01:24 ◼   ► the very first thing I do is set the SDK to require the newest OS

00:01:28 ◼   ► and see all the deprecations and everything, all the stuff I have to change,

00:01:32 ◼   ► and then just start doing it, just start changing all the deprecated enums

00:01:36 ◼   ► to their new values and start adopting all the new APIs

00:01:39 ◼   ► and delete all the code that supported the old APIs and stuff like that.

00:01:42 ◼   ► And when I was 13, there was a good deal of that this summer,

00:01:46 ◼   ► but most of it that I actually adopted to date was trivial stuff.

00:01:51 ◼   ► It was things like enum values that I can just change back.

00:01:55 ◼   ► Most of them were like the type of activity spinners and stuff like that.

00:01:59 ◼   ► And I had adopted the new background APIs,

00:02:02 ◼   ► and I had adopted the theming API, or the system dark mode API,

00:02:07 ◼   ► to kind of override my theme choice.

00:02:10 ◼   ► But it turned out it took very little effort for me to just put all those enum values back

00:02:18 ◼   ► because it didn't matter, the old ones are still supported, they're just deprecated,

00:02:21 ◼   ► and when you build with 13 not as the requirement, you don't even get warned about it.

00:02:25 ◼   ► So I just put all those enum values back.

00:02:29 ◼   ► That took, what, 15 minutes maybe at most, just to make sure I did everything right.

00:02:33 ◼   ► And then I re-added support for the old background API,

00:02:37 ◼   ► which, by the way, works better than the new background API.

00:02:41 ◼   ► The old background refresh, it turns out,

00:02:46 ◼   ► so the old background refresh most of the time would work.

00:02:49 ◼   ► The new iOS 13 background task system appears to not work at all for some people or sometimes,

00:02:57 ◼   ► and I have a frequent bug in the current version where people say search doesn't work.

00:03:02 ◼   ► And that's because I was doing search indexing only with background tasks

00:03:05 ◼   ► because it would kill my app if I did that CPU-intensive job in the background.

00:03:09 ◼   ► So in my dev version that I'm going to release shortly,

00:03:13 ◼   ► it's just doing it whenever you enter a search box.

00:03:17 ◼   ► Whenever you put the cursor in a search box, it quickly indexes things right then.

00:03:21 ◼   ► If anything needs to be indexed, it hasn't been done by the background tasks

00:03:24 ◼   ► that don't seem to execute sometimes anyway.

00:03:26 ◼   ► So I'm kind of working around the need for anything that 13 actually did.

00:03:31 ◼   ► And all those new APIs that I thought I would be using that are 13 and up only,

00:03:38 ◼   ► so things like obviously SwiftUI is the big one,

00:03:41 ◼   ► there's also a whole bunch of other stuff throughout the frameworks,

00:03:43 ◼   ► especially there's Combine and a new Diffable data source

00:03:48 ◼   ► and a new collection view layout system that for making standard table viewing,

00:03:54 ◼   ► especially collection view stuff, there's a bunch of big advantages,

00:03:57 ◼   ► even if you don't want to use SwiftUI.

00:03:59 ◼   ► There's a bunch of big advantages to 13.

00:04:00 ◼   ► So all this new stuff in the APIs that, yeah, it would be nice to be able to use that,

00:04:05 ◼   ► but the fact is I haven't used that yet.

00:04:07 ◼   ► And if I delay myself by another year, well, I've gotten this far.

00:04:14 ◼   ► I've gotten into late January, and I've still had so much more that I want to do in the app

00:04:21 ◼   ► or bugs I have to fix or features I want to add that don't require

00:04:25 ◼   ► or even give me time for new API adoption that I figure if I made it this long,

00:04:31 ◼   ► I can probably make it at least until June or July,

00:04:34 ◼   ► and when I see what iOS 14 adds and then decide from there what my ongoing OS requirements might be.

00:04:40 ◼   ► But until then, I have enough to keep me busy without diving into the 13 APIs.

00:04:45 ◼   ► So therefore, re-implementing iOS 12, I even thought,

00:04:50 ◼   ► now that I've kind of removed the manual toggling of theming,

00:04:55 ◼   ► switching between dark and light mode, I now rely on the system for that.

00:04:59 ◼   ► I thought, well, that's going to be hard to change in iOS 12.

00:05:02 ◼   ► And it turns out I just added one table row above the theme picker that says,

00:05:08 ◼   ► "Are you currently in light mode or dark mode?"

00:05:10 ◼   ► And it shows only in iOS 12.

00:05:12 ◼   ► And so it was really surprisingly easy.

00:05:17 ◼   ► The only big work that I had to do was in my current build,

00:05:24 ◼   ► I basically rewrote the audio engine and was using an Airplay 2 compatible engine,

00:05:28 ◼   ► and that relies on bugs that were fixed in 13.1.

00:05:31 ◼   ► That's a great phrase. Just to interrupt you for a moment, that's a great phrase.

00:05:35 ◼   ► Relies on bugs.

00:05:37 ◼   ► Right. It relies on them having been fixed.

00:05:42 ◼   ► And they were fixed in 13.1.

00:05:44 ◼   ► And so I was going to require 13.1 for this build,

00:05:46 ◼   ► and then when I re-added 12, I thought, well, this entire audio engine has to be not used under iOS 12.

00:05:51 ◼   ► But there were other reasons why I wanted to make a second audio engine

00:05:56 ◼   ► that was based on just AV audio engine,

00:05:58 ◼   ► that the Airplay 2 engine was not working as well as I wanted to when it was not running on Airplay,

00:06:02 ◼   ► when it was just running on your phone, speaker, whatever.

00:06:05 ◼   ► So I made a whole second audio engine that happens to be compatible with 12.

00:06:09 ◼   ► But I was going to do that anyway before I released this.

00:06:12 ◼   ► So the actual additional work required to support iOS 12 in this release was about a half a day of work,

00:06:19 ◼   ► just mostly enum values and adding one row to a table to change the theme manually.

00:06:25 ◼   ► And that's about it.

00:06:28 ◼   ► Which I think does make me kind of think,

00:06:31 ◼   ► because I'm pretty sure we'd recorded an episode in the summer where we were talking about the benefits

00:06:35 ◼   ► and drawbacks of being aggressive with requiring iOS 13 and whether it was a good idea this year.

00:06:42 ◼   ► And I think we both ended up that it was like this was a good year to do it, and we should probably be like...

00:06:47 ◼   ► We sure did.

00:06:49 ◼   ► So maybe you shouldn't be listening to advice from the Under the Radar podcast.

00:06:52 ◼   ► Maybe we should add some kind of disclaimer that turns out that we are potentially sometimes horrifically wrong,

00:06:58 ◼   ► and that's like half a day of work was all you needed to do to continue supporting 12

00:07:04 ◼   ► and all the requisite benefits that come with that.

00:07:08 ◼   ► I think the main differences here, which you talked about two episodes ago,

00:07:11 ◼   ► whenever that was when I mentioned re-adding this,

00:07:13 ◼   ► the main differences that I didn't foresee at least is that I really thought I'd be jumping into the new APIs

00:07:20 ◼   ► way more than I have.

00:07:22 ◼   ► And I also really thought that iOS 13 adoption would be way faster than it has been.

00:07:28 ◼   ► So the combination of both of those factors, I think not going the way that I predicted,

00:07:34 ◼   ► is why this had to require a change of mind.

00:07:38 ◼   ► I had to change my mind on this.

00:07:40 ◼   ► I had to look back and say, "Well, normally I do this, but turns out this time that was the wrong move,

00:07:44 ◼   ► and I'm fixing it now, and I don't know how long I'll keep 12 compatibility,

00:07:49 ◼   ► but it's still important to me today to do it, so I'm going to do it."

00:07:53 ◼   ► And I think the thing that's crazy about that, I've been just keeping an eye on my stats,

00:07:57 ◼   ► and my adoption has essentially leveled off now at about 80% adoption.

00:08:03 ◼   ► And it has not moved at all in the last month or two,

00:08:08 ◼   ► which is making me think that that's probably where it's going to be for a pretty long time,

00:08:13 ◼   ► essentially until the incompatible devices age out and get replaced,

00:08:19 ◼   ► so the 5S, the 6, and the 6 Plus.

00:08:22 ◼   ► But that takes a while on iPhones.

00:08:24 ◼   ► Yeah, that's going to take a long time.

00:08:26 ◼   ► Or it's like somehow there's a new influx of devices that are running the newer OS.

00:08:33 ◼   ► Either the old ones are going to have to go away,

00:08:35 ◼   ► or they're going to have to get eclipsed by the new ones.

00:08:38 ◼   ► But it's been very stable there,

00:08:41 ◼   ► which makes me think even next year we may be in an awkward position

00:08:46 ◼   ► where 12 may just be the one that lingers around for a while,

00:08:51 ◼   ► and that's just where we're going to be living for a while, that 12 is required.

00:08:57 ◼   ► And then if we want to adopt any of the new stuff,

00:08:59 ◼   ► we're going to just have to do it in the--

00:09:03 ◼   ► having the app behave differently between two different systems,

00:09:07 ◼   ► which is complicated potentially and not necessarily great in a lot of ways,

00:09:10 ◼   ► or there might be features that are only available on the new OSes.

00:09:14 ◼   ► There's lots of ways we think problems,

00:09:16 ◼   ► and I'm sure our future selves are going to have to deal with.

00:09:18 ◼   ► But it definitely seems like 12 is going to be part of the conversation for a long time

00:09:23 ◼   ► in a way that 11 just disappeared when 12 came out.

00:09:29 ◼   ► Oh, no. Is iOS 12 our IE6?

00:09:32 ◼   ► It might be.

00:09:33 ◼   ► I think it might be.

00:09:36 ◼   ► Yeah, because 20% of people still not running it is a lot.

00:09:39 ◼   ► That's a lot of people, and that's a lot of the market.

00:09:43 ◼   ► And as I keep--

00:09:45 ◼   ► I'm literally hearing people every day saying,

00:09:47 ◼   ► "I searched for over-caching the app store, and it's not there.

00:09:50 ◼   ► What happened?"

00:09:51 ◼   ► And the answer is always that they're running iOS 12,

00:09:54 ◼   ► and it literally just doesn't even--

00:09:56 ◼   ► your app doesn't even show up if it requires a higher OS,

00:09:59 ◼   ► and that's terrible.

00:10:01 ◼   ► So, yeah, so we got to work on that.

00:10:03 ◼   ► But anyway, so I've been doing a whole lot of that--

00:10:07 ◼   ► well, very little bit of that and a whole lot of other work on this new build.

00:10:12 ◼   ► In terms of-- before we move on to where the other work is, though,

00:10:14 ◼   ► I'm curious, when you're going through and doing that kind of re-adding it,

00:10:18 ◼   ► how do you make sure that you're not re-breaking it in the process?

00:10:23 ◼   ► Are you going through the commit that you did to drop support

00:10:28 ◼   ► and kind of doing the--

00:10:30 ◼   ► having it up in one window and Xcode in the other and kind of just doing the opposites?

00:10:34 ◼   ► Because I would be worried that I would forget something,

00:10:37 ◼   ► and there's some lingering bug or problem that--

00:10:42 ◼   ► I'm reintroducing that I will only hit if I happen to go through a very particular code path,

00:10:48 ◼   ► and then it all falls apart.

00:10:50 ◼   ► No, I mean, really the advantage here was that I really adopted iOS 13 APIs very little.

00:10:57 ◼   ► And so I didn't--

00:10:59 ◼   ► the thing that actually dropped support for it, like the commit back then,

00:11:03 ◼   ► was part of a larger series of commits,

00:11:05 ◼   ► and there's been a lot of changes since then,

00:11:07 ◼   ► so I didn't think it would be wise to try to go back to that and try to back it out somehow.

00:11:10 ◼   ► So instead, I just set the deployment target back and ran it on iOS 12 device.

00:11:16 ◼   ► And if you set the deployment target back and hit Build,

00:11:20 ◼   ► you're going to get a ton of errors from all the new enum values and stuff.

00:11:24 ◼   ► And then I basically went and for the very few APIs that I knew I adopted that are 13 only,

00:11:31 ◼   ► mainly the background task API.

00:11:33 ◼   ► I just did if available checks around that and made a separate code path

00:11:38 ◼   ► for the old background refresh API to work again.

00:11:40 ◼   ► And then I just ran it on an iOS 12 device, and I played around with it for a while.

00:11:44 ◼   ► I tested a bunch of different parts of the app,

00:11:46 ◼   ► because I still have an iOS 12--

00:11:48 ◼   ► I actually ran it on an iPhone 5S, which you can't run 13.

00:11:51 ◼   ► So ran it on that, and I couldn't find any problems.

00:11:55 ◼   ► And then I released it to beta, and it's been in beta with 12 compatibility.

00:11:59 ◼   ► And I do have a lot of test flight people on iOS 12.

00:12:02 ◼   ► So it's been in beta testing now for a couple of weeks,

00:12:07 ◼   ► and so far there's been no problems introduced--

00:12:10 ◼   ► or no problems identified with iOS 12.

00:12:14 ◼   ► Because I had just barely adopted those new APIs.

00:12:19 ◼   ► And so it really didn't take very long at all to re-add the compatibility,

00:12:24 ◼   ► which is a little shameful, like a little unfortunate.

00:12:28 ◼   ► But definitely going all these months between iOS 13's release--

00:12:33 ◼   ► or I guess the week after, whenever I did my update--

00:12:35 ◼   ► between then and now, basically losing 20% of potential new customers or more,

00:12:41 ◼   ► that's going to cost me long term, of course.

00:12:45 ◼   ► That's the penalty for my error here.

00:12:48 ◼   ► And certainly the longer we go without fixing it, the less it needs to be fixed.

00:12:53 ◼   ► But I do think that, as you mentioned, I think we're going to hit a floor

00:12:58 ◼   ► for how low iOS 12 is going to go reasonably for a while.

00:13:01 ◼   ► It'll continue to trickle down slowly, but it's not going to be a rapid change.

00:13:05 ◼   ► So I do still think, even though I've lost whatever it's been four or five months

00:13:10 ◼   ► of those potential sales, it is still worth releasing this now

00:13:14 ◼   ► and regaining the ability to have those sales going forward.

00:13:18 ◼   ► - That makes sense.

00:13:19 ◼   ► - Yeah, and in reality, it's just like, whatever the mistake was,

00:13:23 ◼   ► once you've identified it, you just fix it.

00:13:25 ◼   ► You can't worry about what you potentially could have lost or whatever.

00:13:29 ◼   ► There's no productivity in that.

00:13:31 ◼   ► You identified a mistake and you fixed it, and that's really all we can do.

00:13:36 ◼   ► - Yeah, exactly.

00:13:38 ◼   ► Because there's not a lot of value in regretting your old mistakes.

00:13:43 ◼   ► Just do better going forward.

00:13:45 ◼   ► Anyway, we are brought to you this week by Linode.

00:13:48 ◼   ► Whether you are working on a personal project

00:13:50 ◼   ► or managing your enterprise's entire infrastructure,

00:13:52 ◼   ► Linode has the pricing, support, and scale

00:13:55 ◼   ► that you need to take your project to the next level.

00:13:57 ◼   ► They have now 11 data centers worldwide.

00:13:59 ◼   ► They're always adding more.

00:14:00 ◼   ► This includes their newest data center in Sydney, Australia.

00:14:03 ◼   ► And they have enterprise-grade hardware,

00:14:05 ◼   ► a new S3-compatible storage option, and their next generation network.

00:14:10 ◼   ► So they deliver the performance you expect and at a surprisingly good price.

00:14:14 ◼   ► You can get started today.

00:14:16 ◼   ► Plans start at just $5 a month,

00:14:18 ◼   ► and you can get started today with a $20 credit using our coupon code.

00:14:22 ◼   ► And you can get all sorts of great stuff with this.

00:14:24 ◼   ► They have, of course, those $5 a month plans.

00:14:26 ◼   ► They give you one gig of RAM currently,

00:14:28 ◼   ► and over time, as technology gets better, they always upgrade their plans.

00:14:32 ◼   ► So right now, that's a gig of RAM.

00:14:34 ◼   ► In the future, that may buy you even more, and they give you free upgrade paths.

00:14:37 ◼   ► They also have all sorts of plans above and beyond that,

00:14:39 ◼   ► depending on what your needs are,

00:14:41 ◼   ► including specialties like dedicated CPU plans with cores reserved just for you,

00:14:45 ◼   ► GPU compute plans suitable for AI, ML, and video processing,

00:14:49 ◼   ► one-click installs of popular apps including WordPress, the LAMP stack,

00:14:53 ◼   ► and even Minecraft servers, and so much more.

00:14:56 ◼   ► So go to linode.com/radar,

00:14:59 ◼   ► and use promo code RADAR2020 when creating a new Linode account.

00:15:04 ◼   ► That'll get you $20 credit towards your next project.

00:15:06 ◼   ► And they're hiring right now.

00:15:08 ◼   ► So if that interests you, go to linode.com/careers.

00:15:11 ◼   ► So once again, linode.com/radar to sign up.

00:15:14 ◼   ► Use that promo code RADAR2020 for a $20 credit.

00:15:18 ◼   ► Our thanks to Linode for their support of this show and all of Relay FM.

00:15:22 ◼   ► So all this time that I've been avoiding the new APIs

00:15:27 ◼   ► and doing all sorts of other work,

00:15:29 ◼   ► I've been taking advantage of my current rush of productivity

00:15:33 ◼   ► to cram in a whole bunch of small fixes.

00:15:37 ◼   ► I fixed a weird bug this morning where upload files would fail if they had a comma in them,

00:15:42 ◼   ► a bunch of weird little bugs and fixes that I've been doing,

00:15:45 ◼   ► trying to cram into this as much as possible

00:15:47 ◼   ► because I've had this productivity that I saved by not spending it all,

00:15:50 ◼   ► making iOS 12 compatible,

00:15:53 ◼   ► cramming in a few new features that are high demand, low effort features,

00:15:57 ◼   ► like intro and outro skipping.

00:15:59 ◼   ► So I've crammed all this stuff in.

00:16:02 ◼   ► Meanwhile, you've been adopting a whole bunch of new APIs.

00:16:05 ◼   ► You've kind of been doing the total opposite of this.

00:16:08 ◼   ► - The opposite, yes.

00:16:09 ◼   ► So I'm curious, in a study of contrast here,

00:16:13 ◼   ► how have you, while I've been living in the old days,

00:16:18 ◼   ► what have you been doing?

00:16:21 ◼   ► - So a bit of context is probably helpful.

00:16:23 ◼   ► So I've been really enjoying just working on the Apple Watch,

00:16:28 ◼   ► and that has been my primary focus.

00:16:31 ◼   ► I got my main, sort of like my bread and butter apps updated and stable,

00:16:35 ◼   ► and in general, they all seem to be in a pretty good place right now, feature-wise.

00:16:40 ◼   ► And then I decided I wanted my next project to be something a little bit ambitious,

00:16:46 ◼   ► a little bit kind of like, see how far I could push the Apple Watch.

00:16:50 ◼   ► And so that's what I've been doing, essentially.

00:16:53 ◼   ► And it's a bit early to get into the exact details of what that's going to look like,

00:16:56 ◼   ► but I mean, functionally, I'm trying to see how far you can push the complication system,

00:17:01 ◼   ► the Watch apps, all kinds of fitness and workout modes.

00:17:06 ◼   ► I'm trying to see just how crazy I can get there,

00:17:09 ◼   ► and especially taking advantage of as much of the new stuff that we can do on the Watch with SwiftUI.

00:17:15 ◼   ► So graphically and visually, there's lots of things that we can now do,

00:17:19 ◼   ► and it's been an interesting process.

00:17:24 ◼   ► Parts of it are just amazing,

00:17:26 ◼   ► and it's been really fun to be able to make things like,

00:17:30 ◼   ► I played around a little bit with making games on the Apple Watch using SwiftUI,

00:17:34 ◼   ► and it surprisingly just kind of works great,

00:17:37 ◼   ► and the animations are nice and smooth.

00:17:40 ◼   ► And when SwiftUI works, it is just an absolute delight,

00:17:45 ◼   ► and the code kind of feels like magic,

00:17:47 ◼   ► like the way you combine and the way the data flow works.

00:17:51 ◼   ► I both love it and I absolutely hate it,

00:17:55 ◼   ► which is probably in many ways reflective of the way that I come from with view layout on UIKit,

00:18:02 ◼   ► where I do all my layout with setting explicit frames.

00:18:07 ◼   ► I very much like that kind of layout system,

00:18:10 ◼   ► and I never liked auto layout.

00:18:12 ◼   ► I never liked the magic where you set it up and it just kind of works.

00:18:17 ◼   ► And SwiftUI's data flow system feels very similar to that in some ways,

00:18:21 ◼   ► where you create these state objects,

00:18:25 ◼   ► and any time they change, the changes just flow to where they need to go,

00:18:29 ◼   ► and everything will stay in sync.

00:18:31 ◼   ► And when it works, it's amazing.

00:18:33 ◼   ► But if it doesn't work, or if there's performance issues or problems with it,

00:18:38 ◼   ► it can be very frustrating.

00:18:41 ◼   ► But I think the biggest thing that has been interesting working with this

00:18:45 ◼   ► the last three or four weeks on this

00:18:49 ◼   ► is the most difficult part of working on new APIs

00:18:53 ◼   ► that are not particularly largely adopted.

00:18:57 ◼   ► I don't get the impression that there's huge amounts of...

00:19:00 ◼   ► There's lots of SwiftUI academic use, it seems.

00:19:06 ◼   ► There's lots of really good resources and documentation things,

00:19:11 ◼   ► lots of toy projects and things,

00:19:13 ◼   ► but actually in use with lots of complications.

00:19:16 ◼   ► You start running into all kinds of weird edge cases.

00:19:19 ◼   ► The thing that is most challenging is when you find yourself in this place

00:19:24 ◼   ► where it's like, "Do I not understand how this should work,

00:19:27 ◼   ► and my code is broken?"

00:19:29 ◼   ► Or is this new API, this new capability, just not working?

00:19:35 ◼   ► And the difference between those two things is often...

00:19:41 ◼   ► There's no way to specifically determine that.

00:19:44 ◼   ► "Am I doing it wrong, or is it just not working?"

00:19:47 ◼   ► I had a kind of hilarious one recently, I think I may have mentioned this to you,

00:19:50 ◼   ► where I was doing a thing where in SwiftUI

00:19:54 ◼   ► you can have your navigation hierarchy be based on a state.

00:20:01 ◼   ► So you can say which of the detail views should be visible at any given time,

00:20:07 ◼   ► and the way you do this is each row gets an identifier,

00:20:10 ◼   ► and you say which of the identifiers is active.

00:20:12 ◼   ► And I was using that, and it was working great,

00:20:15 ◼   ► and then I added a few more rows to my table,

00:20:17 ◼   ► and it stopped working for half of the rows,

00:20:20 ◼   ► and it would work for some but not all of them.

00:20:22 ◼   ► It turned out it would only work for a row that was visible on screen.

00:20:27 ◼   ► Which, A, took forever for me to work out, because it worked fine,

00:20:32 ◼   ► it worked fine, and then it just didn't.

00:20:34 ◼   ► And then it's like, you're kind of playing this matching game of,

00:20:36 ◼   ► "Why? If I try and set the value to this row, then it works,

00:20:40 ◼   ► and if I switch to the other one, it just doesn't work."

00:20:42 ◼   ► And so right now in my code I have this horrific workaround

00:20:45 ◼   ► where I have a one-pixel-high row at the top of my thing

00:20:51 ◼   ► that includes all the other rows in it,

00:20:53 ◼   ► and I actually push to those rows and have them change the detail view

00:20:58 ◼   ► rather than the rows that appear on the bottom of the screen.

00:21:00 ◼   ► So that sort of works, but stuff like that is just so complicated to know,

00:21:06 ◼   ► "Am I doing something wrong? Am I misusing this API?

00:21:09 ◼   ► Or is it just a bug and it just doesn't work?"

00:21:12 ◼   ► There's plenty of things still in WatchOS 6 that are just kind of buggy.

00:21:17 ◼   ► You never know if it's just, "Is it me or is it you?"

00:21:22 ◼   ► I don't know. But it's definitely been fun, though, I will say.

00:21:26 ◼   ► And I think I'm enjoying working on something that has a bit of ambition behind it,

00:21:31 ◼   ► that I feel like a lot of my projects previously have been interesting,

00:21:38 ◼   ► and they've been challenging in their own ways.

00:21:42 ◼   ► But what I've been enjoying about this project in particular

00:21:44 ◼   ► is that I'm taking so many parts of the last ten years of work

00:21:49 ◼   ► I've been doing on Apple platforms and kind of combining it all together.

00:21:52 ◼   ► And so it's this really interesting kind of Voltron experience

00:21:56 ◼   ► that is pulling all these parts together,

00:21:58 ◼   ► all these different experiences I have,

00:22:00 ◼   ► and then smooshing them all together in kind of an ambitious way.

00:22:03 ◼   ► So that part's been fun.

00:22:04 ◼   ► SwiftUI and its error messages continue to be just horrifically comical,

00:22:09 ◼   ► though apparently I do believe, last I heard, the latest--

00:22:13 ◼   ► I'm not on the Swift developer mailing list sort of things,

00:22:16 ◼   ► but I remember hearing someone saying that the first version

00:22:20 ◼   ► of the new Swift error message system is now out in beta.

00:22:25 ◼   ► And so I look forward to hopefully that making my life much better,

00:22:28 ◼   ► where the error messages maybe will actually point to the line of code

00:22:32 ◼   ► that is actually the problem rather than just pointing to some random line

00:22:36 ◼   ► and giving me strange messages.

00:22:38 ◼   ► My favorite one recently was I was passing--

00:22:43 ◼   ► at some point I'm passing a zero into a frame width or something,

00:22:49 ◼   ► and then I make a change ten lines down,

00:22:52 ◼   ► and the change had a bug in it. Fair enough. That was my fault.

00:22:57 ◼   ► But the error message I get was ten lines up.

00:22:59 ◼   ► It said the zero could not be converted to an int.

00:23:02 ◼   ► And I didn't know what that means.

00:23:06 ◼   ► I still don't really know what that means

00:23:08 ◼   ► or what to make of that particular error message,

00:23:11 ◼   ► but that's my life now.

00:23:14 ◼   ► Yeah, this is--

00:23:16 ◼   ► this couldn't be more different than the kind of thing I'm doing.

00:23:20 ◼   ► But I see there are times--

00:23:24 ◼   ► there are--my development kind of goes in various cycles or seasons,

00:23:29 ◼   ► as we've talked about before.

00:23:31 ◼   ► And there are times when I'm in an exploration or expansion

00:23:35 ◼   ► or new construction phase,

00:23:37 ◼   ► where using a whole bunch of new stuff like this

00:23:40 ◼   ► is actually what I want to do and what I enjoy doing

00:23:43 ◼   ► and oftentimes is the right move.

00:23:45 ◼   ► And right now I'm not in one of those phases.

00:23:47 ◼   ► Right now I'm in a refinement and small fixes kind of phase

00:23:52 ◼   ► as I prepare to launch this big update.

00:23:55 ◼   ► But I totally get the appeal of that.

00:23:58 ◼   ► And there will be a time when I will join that,

00:24:02 ◼   ► that exclusive club of Swift UI users.

00:24:05 ◼   ► I don't think that time is soon for me.

00:24:08 ◼   ► But next time I get into a new construction phase,

00:24:13 ◼   ► that's probably what I'm going to want to do.

00:24:15 ◼   ► Yeah.

00:24:17 ◼   ► And it's--I think the thing that's tricky, though,

00:24:19 ◼   ► is there's part of me that sometimes is like,

00:24:21 ◼   ► is this--I guess maybe the thing that I'm trying to be

00:24:24 ◼   ► very thoughtful of is, am I using Swift UI

00:24:26 ◼   ► or the related new technologies

00:24:28 ◼   ► because they're the best tool for the problem

00:24:30 ◼   ► or because they're the new tool?

00:24:32 ◼   ► Because I feel like that's the biggest trap

00:24:34 ◼   ► that I have to keep honest with myself about,

00:24:37 ◼   ► is sometimes I've--like, some of my things

00:24:40 ◼   ► I've just rolled back to using WatchKit in

00:24:43 ◼   ► because WatchKit was better for whatever reason.

00:24:47 ◼   ► And then a lot of times it's just because it's simpler

00:24:49 ◼   ► or it's more performant.

00:24:51 ◼   ► Like, WatchKit is very straightforward,

00:24:53 ◼   ► or at least I know where all the rough edges are.

00:24:56 ◼   ► Like, every single one of them I've hit, I'm sure.

00:24:58 ◼   ► And so I know how to do that.

00:25:00 ◼   ► And so sometimes I have to be like, look, like,

00:25:03 ◼   ► Swift UI is cool and could make this, like, slightly shinier.

00:25:07 ◼   ► But I need to be thoughtful about the fact that, like,

00:25:10 ◼   ► it may not actually be the right tool for the job.

00:25:13 ◼   ► And I think that's--I think the biggest advice

00:25:16 ◼   ► I would give to anyone kind of--just to anyone

00:25:18 ◼   ► when we're adopting these new things is,

00:25:20 ◼   ► it's making sure that you're adopting it because

00:25:22 ◼   ► it's better and appropriate for the job that needs to be done

00:25:26 ◼   ► and is actually going to tangibly improve the application

00:25:29 ◼   ► as a result versus just because it--

00:25:32 ◼   ► adopting it because it's cool.

00:25:33 ◼   ► Because more likely--because, like, inevitably

00:25:35 ◼   ► it's going to come with drawbacks and problems

00:25:37 ◼   ► and bugs and issues.

00:25:39 ◼   ► And so those--all those negatives have to be

00:25:41 ◼   ► sort of outweighed by the positives.

00:25:43 ◼   ► Like, the new stuff that in UITableView,

00:25:46 ◼   ► like, the DiffableDataSource stuff,

00:25:47 ◼   ► it's really cool and can do some, you know,

00:25:49 ◼   ► some cool, like--have some--gives you some--

00:25:53 ◼   ► it gives you some great stuff for free,

00:25:55 ◼   ► but it also, like, comes with some costs and some complexities,

00:25:58 ◼   ► and you have to restructure, you know,

00:26:00 ◼   ► how you're getting your data source

00:26:01 ◼   ► and may have some complicated questions with memory

00:26:04 ◼   ► and, you know, how many of your objects

00:26:07 ◼   ► you actually have to have in memory at any one time.

00:26:09 ◼   ► And so, like, I've looked into that,

00:26:11 ◼   ► and I've adopted it, I think, in one place in my app,

00:26:14 ◼   ► but several other spots, I'm just like,

00:26:16 ◼   ► "I'm just going to do this the old-fashioned way,"

00:26:18 ◼   ► and not worry so much about, you know,

00:26:21 ◼   ► the fact that I'm missing out on the new hotness

00:26:23 ◼   ► and instead just like, "No, this is, like--

00:26:26 ◼   ► this just needs the boring solution

00:26:27 ◼   ► rather than the new solution."

00:26:29 ◼   ► - Yeah, I think kind of a theme to my arc

00:26:32 ◼   ► through iOS 12 and into iOS 13,

00:26:34 ◼   ► now back to iOS 12 compatibility,

00:26:36 ◼   ► is kind of that I overestimated the gains I would get

00:26:41 ◼   ► by doing that, and I underestimated the costs

00:26:44 ◼   ► of just doing new stuff or only supporting new stuff.

00:26:48 ◼   ► And in every OS release every year

00:26:51 ◼   ► and for different markets, those are different.

00:26:54 ◼   ► Like, I was applying my old wisdom

00:26:57 ◼   ► that had always worked for me to date,

00:27:00 ◼   ► which was just support the new thing,

00:27:02 ◼   ► adopt everything immediately, that's better for most indies.

00:27:04 ◼   ► But that wasn't better for me this time.

00:27:06 ◼   ► And so it's important to, you know,

00:27:09 ◼   ► keep an open mind about that, that, you know,

00:27:11 ◼   ► what you've done in the past in either direction,

00:27:12 ◼   ► either supporting old stuff forever

00:27:14 ◼   ► or jumping on new stuff immediately

00:27:16 ◼   ► or anything in between, whatever you've done in the past

00:27:19 ◼   ► might not hold this time around or next time around

00:27:22 ◼   ► because conditions are different.

00:27:24 ◼   ► You know, OS releases are different,

00:27:25 ◼   ► hardware support is different, like, you know,

00:27:27 ◼   ► it changes every time.

00:27:29 ◼   ► And the value of supporting only the new stuff also changes

00:27:34 ◼   ► because in different years that'll be--

00:27:37 ◼   ► it'll be harder or easier, you know,

00:27:39 ◼   ► to maintain backwards compatibility.

00:27:41 ◼   ► The new APIs will be more or less compelling

00:27:44 ◼   ► and they'll be more or less specialized.

00:27:46 ◼   ► Like, you know, the iOS 13 API for dark mode

00:27:50 ◼   ► is pretty specialized, so there's one feature in iOS 13

00:27:53 ◼   ► and if you adopt that API, it doesn't really make it

00:27:55 ◼   ► any harder to support the old way of doing things.

00:27:58 ◼   ► If you adopt SwiftUI, then it makes it almost impossible

00:28:01 ◼   ► to keep compatibility because you basically have

00:28:03 ◼   ► to write your entire UI twice or somehow implement

00:28:05 ◼   ► SwiftUI yourself for iOS 12, which is a terrible idea.

00:28:09 ◼   ► You shouldn't do that.

00:28:10 ◼   ► (laughs)

00:28:11 ◼   ► And so, you know, every time you are faced with this choice,

00:28:15 ◼   ► you should reevaluate based on the current conditions.

00:28:19 ◼   ► Ask around, do some research, see if you can find

00:28:21 ◼   ► good numbers on adoption, things like that.

00:28:23 ◼   ► And really think, like, is it the right move

00:28:26 ◼   ► to adopt the new shiny thing in this case

00:28:28 ◼   ► at the expense of compatibility?

00:28:31 ◼   ► And if you're building something brand new from scratch,

00:28:33 ◼   ► it probably is.

00:28:35 ◼   ► If you're pushing your app update forward, it might not be.

00:28:39 ◼   ► - Yeah, and I think what's interesting too,

00:28:41 ◼   ► what's awkward is that the only way to really know the cost

00:28:45 ◼   ► is to actually try it to some degree.

00:28:47 ◼   ► That is much as you kind of want to estimate it,

00:28:49 ◼   ► but I think there is certainly a value in doing

00:28:53 ◼   ► the kind of like quick explorations to get a sense of things.

00:28:57 ◼   ► I think you can give yourself a lot more information

00:28:59 ◼   ► and make better choices as a result.

00:29:01 ◼   ► I think about how it ended up the try iOS 12 compatibility

00:29:04 ◼   ► was half a day or so, and if like, towards the end

00:29:08 ◼   ► of the summer, had just been like, huh, I wonder

00:29:10 ◼   ► what it would take to add 12 support.

00:29:13 ◼   ► And it'd be like, I'll give myself half a day to work on it

00:29:16 ◼   ► and see how far I can get.

00:29:18 ◼   ► And if you've just gotten to the end and you had it all

00:29:20 ◼   ► in there, it's like, okay, maybe I'll just ship this then.

00:29:22 ◼   ► - Yeah, exactly.

00:29:23 ◼   ► - So it's good to, I think, be thoughtful and explore

00:29:26 ◼   ► in that way, but understand that sometimes you are

00:29:28 ◼   ► just gonna have to try it and then just be thoughtful

00:29:31 ◼   ► about not getting stuck in a hole just because you've started

00:29:34 ◼   ► doesn't mean you have to finish.

00:29:36 ◼   ► Thanks for listening everybody, and we'll talk to you

00:29:38 ◼   ► in two weeks.

00:29:39 ◼   ► - Bye.

00:29:40 ◼   ► [BLANK_AUDIO]