00:00:00 ◼ ► Welcome to Under the Radar, a show about independent iOS app development. 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:10 ◼ ► So I ran into a bit of, I don't know how I would describe it necessarily, a scope avalanche maybe?
00:00:21 ◼ ► The very first time I ran Overcast with the iOS 15 SDK. So if I run Overcast as built with the iOS 14 SDK,
00:00:36 ◼ ► So I'm not under any kind of emergency push that once iOS 15 is released, I must have a certain update out to fix major problems with it.
00:00:45 ◼ ► Fortunately, I don't have that. However, there was a little visual glitch that would happen here and there
00:00:56 ◼ ► And as you may be aware, the core of Overcast UI is a bunch of UI navigation controllers basically.
00:01:05 ◼ ► I have kind of like one main navigation tree, and I use navigation pushes for lots of screens,
00:01:12 ◼ ► as opposed to modal overlays. I use a lot of navigation pushes. So many things, like settings, downloads,
00:01:20 ◼ ► and then of course the main podcast list, playlist/podcast view, episode info that might get pushed over from that.
00:01:27 ◼ ► And then at the bottom I have this wonderful little mini player that I've had a bunch of different versions of over the years
00:01:32 ◼ ► that kind of takes the place of a toolbar but can be optionally hidden or shown if there is or is not a currently playing item.
00:01:47 ◼ ► That whole controller, that whole column manager, navigation, toolbar thing, that's all custom.
00:01:54 ◼ ► The navigation controller is not. It's a regular UI navigation controller, but the rest of that is all custom UI.
00:02:00 ◼ ► It's a custom master view controller that has these various sub-view controllers under it, these child view controllers.
00:02:10 ◼ ► Now, to get this to work with UI navigation controller, over the years has occasionally required a bit of tweaking here and there.
00:02:20 ◼ ► A few little bits of code here and there, a few little one-liners, a bit of sub-classing here and there to override things like
00:02:45 ◼ ► No, I know. It's things like how when you have your own view controller, like custom child view controller hierarchy going on,
00:02:58 ◼ ► And you'll have content that accidentally goes under a view controller or a navigation bar,
00:03:02 ◼ ► or you'll have things like the scroll indicator, like the bottom of the scroll indicator is 40 pixels too high off the bottom of the view
00:03:16 ◼ ► So I have lots of different UI code that works around all those different things to make my custom UI work.
00:03:33 ◼ ► I believe I mentioned this on the show before, but a few years back, an iOS developer that we know posted on Twitter.
00:03:42 ◼ ► It was during the Halloween time and when everyone changes their name to something spooky.
00:03:53 ◼ ► It's by far, like anyone who's ever worked with this before, it's just a sense of chill on your spine.
00:04:00 ◼ ► And so I have multiple views in my app that have search bars that are all part of this navigation hierarchy.
00:04:16 ◼ ► Because normally when you have a controller that has a search bar and you push it over to push to the next controller,
00:04:37 ◼ ► I've dealt with the inherent weirdness and bugginess of UI search controller over time.
00:04:41 ◼ ► And all sorts of fun stuff like that, all wrapped in my custom media controller that is my 3-pane layout.
00:04:52 ◼ ► Naturally it's all Objective-C, because this is all before my Swift revolution, I guess.
00:05:08 ◼ ► If there is a modern API that has introduced an iOS 13 to do something, I probably don't use it yet.
00:05:27 ◼ ► the problem was, when the navigation controller would push a new view controller onto the navigation stack,
00:05:35 ◼ ► the navigation bar, which is supposed to be opaque, would briefly flash transparent during the push,
00:05:59 ◼ ► If I want to use any of the new 15 features, which I do, I've already written some stuff against them,
00:06:45 ◼ ► I think it's called UIBarAppearance, and their subclasses UINavigationBarAppearance and UIToolbarAppearance.
00:07:17 ◼ ► So, you know, it's, and then the old, and the new one has almost all those same properties.
00:07:30 ◼ ► So there's even more classes and classes and classes and classes that you have to instantiate.
00:07:35 ◼ ► You have to actually make a configuration object, and then make that configuration object,
00:07:41 ◼ ► Anyway, so, as soon as I switched to the new API, it did indeed fix that transparency bug in the navigation bar.
00:07:53 ◼ ► And this is, you know, this is the difference of like four lines of code overall, really.
00:08:03 ◼ ► Just switching to this new API to set, like, bar translucency from the navigation bar broke edge insets,
00:08:39 ◼ ► So, let me go through and on every single view controller, set, like, you know, the edge inset thing to exclude the top edge.
00:08:57 ◼ ► You might not understand, audience members, when you think of a podcast app, how many screens are there in a podcast app?
00:09:09 ◼ ► Like, you might start counting up, all right, well, you know, you got, like, a list of podcasts, you got a list of episodes,
00:09:14 ◼ ► and you got, like, you know, an outplaying screen, and maybe some kind of, like, ad podcast screen, right?
00:09:19 ◼ ► I don't know the number, but I can tell you I have probably at least 30 screens in Overcast.
00:09:25 ◼ ► There's so many, like, it's, 'cause you don't realize, like, there's so many screens for things like adjusting preferences,
00:09:31 ◼ ► or adjusting, or adjusting behavior, showing different parts of things, showing different versions of podcasts,
00:09:37 ◼ ► different parts of the ad screen, different parts of the setting screen, different part, like, there's so many screens.
00:09:43 ◼ ► And this is why, like, I've been dreading any kind of UI redesign, because there are just so many screens.
00:09:50 ◼ ► And if I change something fundamental, like, suppose I change, like, even just, like, when I change the default font to the system font,
00:09:58 ◼ ► I had to really go through a lot, and do a lot of testing and everything, and there's so many, like, new APIs that I should be using in tons of places,
00:10:07 ◼ ► that do things like, you know, better handling of very large text sizes, with, like, automatic wrapping and stuff like that,
00:10:12 ◼ ► like, automatic table cell sizing, there's so much stuff I should be doing, but I'm, like, buried under this massive weight.
00:10:27 ◼ ► And it's so easy to get something subtle that's, like, a little bit wrong on one of the screens, and not catch it myself,
00:10:34 ◼ ► not catch it with thousands of beta testers, and actually release it into the world, and then somebody writes in and says,
00:10:41 ◼ ► So, I start going through, and I start doing these little, like, patchwork fixes to various view controllers in the app.
00:10:48 ◼ ► And I know, first of all, I'm not gonna get them all. Like, I'm just not. It's impossible for one person to know, to actually get these all.
00:10:57 ◼ ► Even if I was, you know, doing some kind of really advanced test-driven development, Casey,
00:11:03 ◼ ► I still would probably miss some subtle, like, you know, wrong animations here or there, or, like, this text on this control is wrapping a little bit wrong, or something, you know.
00:11:13 ◼ ► So, anyway, so I'm going through the whole app, going through all this stuff, and realizing, first of all, even just to fix the basic thing of, like,
00:11:24 ◼ ► just fixing the, like, content under the navigation bar, or the scroll indicator being too far up because it's missing the safe area,
00:11:45 ◼ ► Because, of course, because something changed, because my entire view hierarchy is a series of hacks to try to get search controllers working, basically.
00:11:55 ◼ ► Like, so many of the hacks that I have to do are either to get navigation controllers working the way I want, or to get search controllers working the way anybody would want them to work.
00:12:06 ◼ ► Like, that's, that's, like, the vast majority of my UI hacks. And the navigation controller really threw me for a loop this time.
00:12:14 ◼ ► I think I almost have it tamed. The search controller I really don't. And so I'm looking at having to potentially, like, remove the search controller and possibly write my own.
00:12:27 ◼ ► Like, just put a search bar there, and then do my own, like, overlay hack to overlay the results on top of the main view controller or something.
00:12:35 ◼ ► You know, I haven't looked into that option too much yet, because I really don't want to do it. But I think I might have to do it.
00:12:42 ◼ ► But anyway, all this is to say, I started out with, "Hey, the navigation bar blinks into translucency during animations. That's wrong."
00:12:51 ◼ ► I changed four lines of code to fix that, and now I have to, like, rip out massive chunks of my UI, rewrite some, rearrange some.
00:13:01 ◼ ► And I thought, and I didn't even attack this problem until now, the middle of the summer.
00:13:08 ◼ ► Because when I first ran it when I was fifteen, like, you know, there was a bunch of, like, little deprecations I wanted to deal with, and a couple new features I wanted to, I wanted to experiment with, and things like that.
00:13:16 ◼ ► So I thought, "Oh, that little navigation bar transparency bug, either it's a bug in the OS, and they'll fix it themselves sometime in the next few betas, and so I won't even have to deal with it.
00:13:26 ◼ ► Or it'll be, like, you know, one afternoon to fix it, and I'll do it later in the summer when I'm done with all the exciting new stuff."
00:13:34 ◼ ► And now it's turned into, "Oh no, the fix to this required, like, removing structural members from my app accidentally."
00:13:42 ◼ ► And now I have to, like, consider, I don't know what, like, possibly rewriting large chunks of view controller hierarchies, rewriting significant parts of the view controllers themselves that use search bars.
00:13:54 ◼ ► And I'm thinking, like, should this now trigger, my redesign I've been wanting to do for a long time, but I don't really have necessarily time for that.
00:14:10 ◼ ► But first, let's talk about our sponsor this week. It is Best in Class iOS App. This is a book series.
00:14:17 ◼ ► And the Best in Class iOS App book series is here to help take your apps from good to great.
00:14:24 ◼ ► Now, this was based on a blog post that I actually read. It came out a couple of years ago, and I read it, and it really resonated with me.
00:14:34 ◼ ► But what I love about this blog post is that it goes through, like, so many, like, modern Apple technologies.
00:14:39 ◼ ► Like, so it's basically, it was like everything I was doing wrong or should have been adopting but wasn't. You know, things like adopting modern APIs to enable modern features.
00:14:56 ◼ ► And what the author of this, Jordan Morgan, has done with Best in Class iOS App book series is he's taken, like, those main bullet points and is actually developing them into a full-blown book.
00:15:10 ◼ ► So each one of those is expanded upon. So he's an indie developer, just like us, and he is covering in his book all he knows about what he believes are the four most critical topics to develop quality iOS software.
00:15:27 ◼ ► And this is, he covers these in great detail. You know, accessibility, you've got to design your apps for everyone.
00:15:33 ◼ ► You know, you master the basics, then he dives deep into APIs like the rotor control, how to best support a voiceover.
00:15:39 ◼ ► And then the accessibility section is pretty much done. And he's still writing the rest.
00:15:45 ◼ ► So there's a design section coming up. Every, you know, good app eventually wins with design, but that can look different for each app.
00:15:52 ◼ ► So he's going to help you figure out your app's voice and use that to make it look and feel right at home on the iOS platform.
00:16:06 ◼ ► And then the iOS API section is an exhaustive look at all the major iOS frameworks and APIs.
00:16:10 ◼ ► So you learn about things like WidgetKit or Siri APIs, make sure your app is tightly integrated across the system and gives people the features they want.
00:16:23 ◼ ► So the accessibility section is almost done now. The design section is going to be, I think, be next.
00:16:33 ◼ ► So it's great. So there's, the accessibility book has over 100 pages of content so far, over 30 code samples.
00:16:47 ◼ ► Lots of stuff that, you know, I've been writing accessibility code in my apps for a long time.
00:16:52 ◼ ► And so I actually learned something, I learned a few things already and hopefully will be learning more.
00:17:05 ◼ ► So you get the whole book for just $80 up front and then you get the whole thing as it comes in.
00:17:10 ◼ ► It gives you all the books in the series, a comprehensive Xcode project with all the code samples,
00:18:02 ◼ ► I've gone down this road before where you have the like, "You make just one little change.
00:18:16 ◼ ► where there is an old legacy sort of code path infrastructure that Apple still supports internally.
00:18:33 ◼ ► And I have no idea if this is actually accurate, but this is an experience I've had before.
00:18:47 ◼ ► And so it feels like, "Oh, I just changed the transparency. That's all that should change."
00:18:57 ◼ ► and table view and search controller and everything to now iOS 15 of all of those things."
00:19:18 ◼ ► where you make a small change and all of a sudden there's this big cascading flow of pain and suffering.
00:19:48 ◼ ► But even that is a pretty vague thing, because you're not really making the app even better.
00:20:00 ◼ ► Second, it's just so funny, my initial reaction, and this is maybe very telling about the kind of developer I am,
00:20:31 ◼ ► It's like, how many fingers do we need to get into this dam before eventually it just completely falls apart?
00:20:54 ◼ ► But yeah, it's rough, because I don't... I think if I was in your shoes, I wouldn't want to do a whole bunch of work
00:21:07 ◼ ► that is just making UI Search Control, or building your own UI Search Control, or even worse,
00:21:15 ◼ ► working around those types of bugs, when especially, I feel like in the back of your mind for a long time,
00:21:27 ◼ ► or you have a bigger change to the app that I think would be more impactful and more exciting to work on,
00:21:33 ◼ ► and actually feel like the app is getting better and moving forward, rather than just putting lots and lots of bandages
00:21:47 ◼ ► And in some ways, are you just putting more bandages on something that eventually this is just completely going to fall down?
00:21:54 ◼ ► And that's rough. Because obviously, Apple itself is in this weird place where I feel like so much of their attention and effort
00:22:04 ◼ ► is going down into SwiftUI, which is like rewriting Overcast in SwiftUI is hardly like,
00:22:12 ◼ ► "Oh yeah, let me just spend a month and do that." Because an app like that has so much inherent UI logic to it.
00:22:21 ◼ ► And I ran into this with Pedometer++. I recently did a little bit of just playing around.
00:22:30 ◼ ► And it's like, "Oh, no." The number of just little things that I've done over the years have accumulated into something that is really hard,
00:22:39 ◼ ► and there are a lot of features and nuances and things that I really like about my UI that would be hard to implement
00:22:45 ◼ ► or impossible to implement or just would take a huge amount of time that isn't actually helping anything.
00:22:50 ◼ ► I feel like people who haven't done iOS apps or similar kinds of challenges before might not realize what percentage of the code in an app is UI code.
00:23:02 ◼ ► You might think Overcast is this big audio engine or something or the sync engine. No, Overcast is a massive pile of UI on top of a fairly small audio engine and data layer.
00:23:25 ◼ ► By the way, I find SwiftUI kit work to be very painful. The "init with code" thing, why they haven't fixed Vue controllers in Swift yet, I don't know.
00:23:38 ◼ ► But anyway, they haven't, as far as I know. SwiftUI is great, and I would love to do more of the app in SwiftUI.
00:23:46 ◼ ► But even though SwiftUI will end up saving a bunch of code, that would still be a year-long project.
00:23:53 ◼ ► Yeah, and that wouldn't get you... It's just hard to know if it actually makes it better.
00:24:03 ◼ ► There's a countdown timer that is now running, that you have been made aware of, that may have been running for a long time, but now you're sort of made aware of.
00:24:12 ◼ ► That there are some aspects of the way that you're interacting with the UI kit that Apple has moved away from, and your use of it is problematic.
00:24:21 ◼ ► And I think the interesting question is, should you try and find a way to just work around this for this little bit, and start thinking about, and knowing that you have a bit more urgency on your grand, sort of, redesign path?
00:24:36 ◼ ► Or try and work around it, and hit yourself in the head with UI Search Controller for the next month?
00:24:43 ◼ ► It's hard. I wish I had a better answer for you in this, and this is why I think in some ways it's a great topic that you brought up, because these are the kind of decisions that as developers, and especially as indie developers, you kind of just find yourself with where it's like, there's no right answer here.
00:24:58 ◼ ► There's no easy, "Oh, of course you could do this," other than, of course, putting a view up behind the nav bar, which will totally solve your problems. That is the easy answer.
00:25:08 ◼ ► But other than that, which is actually not the answer. If I can get it there, see, how do I, like, because that's probably within UI Navigation Controller, I'd have to probably sub-view dive UI Navigation Controller, which I really probably shouldn't be doing.
00:25:18 ◼ ► Maybe. I mean, maybe it's there. I think maybe you can set a background view. Maybe you can put a view in your view that's at the top, but offset underneath the nav bar. There are ways.
00:25:30 ◼ ► There are definitely ways that you could do this. I'm not saying there are good ways, but I'm just saying that they might exist. And it doesn't really solve the problem, because obviously something's going on between those two things.
00:25:41 ◼ ► And it may be different. You get into really weird things, like it might be very different on the iPad, or it might be different on different sizes.
00:25:47 ◼ ► And it's a tough place to find yourself when you're dealing with this. It also makes me wonder if you're... I have had enough experience doing UI kit work over the years, where as much as I think you probably feel like you've pulled on the thread far enough that you have a sense of the scope of it.
00:26:10 ◼ ► There's no telling if you're going to unearth an entire another box of this. In changing, "Oh, you changed from UI Search Controller to something else." Well, now you've actually turned off this other flag over here that is now changing everything about everything.
00:26:27 ◼ ► It's not a good place. My instinct is to do as little as you can to get it working, and to put the effort into things that are going to pay off better in the long run.
00:26:41 ◼ ► And if the little effort is what you've been doing, and going down the Search Controller view stuff, then that's just what you've got to do. But I would aim for as little as possible now, and hasten the arrival of bigger changes down the road, but not with the pressure of trying to get it done with iOS 15, or with urgency for this fall.
00:27:07 ◼ ► That can be something that maybe you're launching next spring, say. But overall, I think that's where my heart goes, but mostly my heart just breaks for you.
00:27:15 ◼ ► Thanks. Yeah, because it really does feel like there's no good answer here. Part of the long-term lesson here is for people like me who don't enjoy all this UI customization work, to just stop customizing the UI so much.
00:27:37 ◼ ► I think there's a lot to be said for maybe I just shouldn't have built a lot of this custom stuff, or maybe I should have used the stock stuff even more, and avoided things like Search Controller if I could.
00:27:48 ◼ ► But that's obviously a harder thing to do. Maybe there's a way I can structure my UI to just put search on its own screen, and not even have it be part of the main view controllers.
00:27:58 ◼ ► Like maybe just change the search box to a search button that pushes a modal screen up and is a search view there. So there are ways I can do that, but it's not as nice.
00:28:09 ◼ ► Yeah, and it speaks to, I think, too, I remember which version of Overcast this was, but there was one that was the big deal was that you put search everywhere. I remember that being a big feat, and it was like, "Oh, you can now search your main podcast list. If you go into the ad podcast thing, you can search there."
00:28:25 ◼ ► And you did your clever stuff where you have a local cache of search history, so it's super fast for the most likely search things. It's just fascinating to me in some ways, and maybe another sort of broader lesson that we can pull is that sounds good at the time,
00:28:40 ◼ ► but it also, you set yourself up for this in the future. And you had no idea at the time that adding that feature and adding that capability was sort of setting yourself up for in the future where UI Search Controller was going to ruin your summer.
00:28:53 ◼ ► So it's just like being thoughtful about those features is probably wise. It's just a vague general lesson there where I've done that same thing many times where I add something that I think is going to be easy, and I don't think it's going to have a lot of lasting impact.
00:29:13 ◼ ► Yeah. Well, I'm going to go back into it and see what I can figure out. Thank you for your guidance.