PodSearch

Under the Radar

180: Shortcuts & Harnesses

 

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:10 ◼   ► So today's episode is going to be kind of in the...

00:00:15 ◼   ► If we were a news website, this would be the article with the title like "Seven Crazy Hacks

00:00:21 ◼   ► That You Won't Believe."

00:00:23 ◼   ► Or more practically, this is the...

00:00:26 ◼   ► I've been thinking a lot about kind of weird or interesting workarounds or approaches I've

00:00:30 ◼   ► been taking to work around either limitations in the platform or just things that I do on

00:00:36 ◼   ► a regular basis to make my development process more efficient, more straightforward, and

00:00:42 ◼   ► ultimately in a lot of ways just more sane.

00:00:45 ◼   ► That these are little things or tweaks or things that I've done that I've just found

00:00:49 ◼   ► make my life a little bit easier.

00:00:50 ◼   ► And I think that it's like whenever I find these things, I feel like they're useful and

00:00:53 ◼   ► worthwhile sharing because maybe they can make...

00:00:56 ◼   ► Maybe they're very specific to my situation, but my situation is probably somewhat similar

00:01:01 ◼   ► to at least some other developers out there, so it seems worth sharing.

00:01:06 ◼   ► So the first one of these, and just to get the flavor of the kind of thing I'm talking

00:01:09 ◼   ► about is...

00:01:10 ◼   ► So developing for the Apple Watch is something that is the actual on-device testing and working

00:01:17 ◼   ► with that is something that I find very cumbersome is probably the kind way to say that.

00:01:22 ◼   ► That's an understatement of the year right there.

00:01:25 ◼   ► So it is like actually getting your app to transfer over to the watch, have it launched,

00:01:31 ◼   ► have it debug correctly and successfully.

00:01:33 ◼   ► All of those things are just...

00:01:36 ◼   ► It's just cumbersome.

00:01:37 ◼   ► And that's just sort of in some ways inherent in it being a wireless debugging session and

00:01:41 ◼   ► there's lots of complexity around that.

00:01:43 ◼   ► It's going via your phone and it's getting better, but it's still not great.

00:01:47 ◼   ► But I find that the nature of watch development requires a certain degree of on-device testing

00:01:56 ◼   ► to really be checking and looking at things, because it's such a small screen that if I

00:02:02 ◼   ► spend too much time just in the simulator on my Mac, I don't get a great sense of how

00:02:07 ◼   ► things would actually work in practice, how big a button would be, how legible some text

00:02:12 ◼   ► would be in practice.

00:02:13 ◼   ► And this is sort of magnified by dealing with the fact that you have even small and relatively

00:02:21 ◼   ► large Apple Watch screen sizes going from the 44mm series 4 and 5 to the 38mm series

00:02:27 ◼   ► 3.

00:02:28 ◼   ► There's a pretty wide range in size there.

00:02:31 ◼   ► And this was something that was causing me a lot of difficulty, and so I kind of cast

00:02:33 ◼   ► around trying to come up with a reasonable solution.

00:02:36 ◼   ► And what I ended up with was something that I thought was kind of interesting.

00:02:39 ◼   ► So the screen resolution, or the screen DPI, pixel density of the Apple Watch is 326 DPI.

00:02:48 ◼   ► This is an OLED screen and it's rendered at 2x, which turns out to be very similar to

00:02:54 ◼   ► the iPhone XR and 11, which are also 326 DPI, 2x, their LCD rather than OLED.

00:03:02 ◼   ► So there's certainly a difference there.

00:03:04 ◼   ► Which has then led me to a place where I now, for a lot of my visual development for Apple

00:03:10 ◼   ► Watch, have built these kind of weird test harnesses where I take my UI as I expect to

00:03:18 ◼   ► render it for the Apple Watch and render it instead on a XR that I have kicking around.

00:03:25 ◼   ► And I can get a great sense of how things appear visually, how they work on different

00:03:29 ◼   ► screen sizes, how anything other than probably color, because color is going to be a bit

00:03:34 ◼   ► tricky, either most different between those two technologies.

00:03:37 ◼   ► But general physical size and legibility are more similar.

00:03:40 ◼   ► And I found this to be a great tool for this.

00:03:42 ◼   ► And I use a XR rather than the older, there's several older iPhones that also had 326 DPI,

00:03:47 ◼   ► 2x screens.

00:03:48 ◼   ► I think all of them from the iPhone 4 forward?

00:03:51 ◼   ► Probably.

00:03:52 ◼   ► But the great thing about the XR is its screen is large enough that you can actually fit

00:03:56 ◼   ► all four of the Apple Watch screen sizes on a XR screen.

00:04:01 ◼   ► That's awesome.

00:04:02 ◼   ► Currently.

00:04:03 ◼   ► So you have all the watch sizes on a phone at the exact right physical sizes so you can

00:04:09 ◼   ► test the interactivity and whether the stuff is too small and everything?

00:04:13 ◼   ► Roughly, yeah.

00:04:14 ◼   ► That's awesome.

00:04:15 ◼   ► That is basically what you can do.

00:04:16 ◼   ► Because the XR screen is actually pretty big.

00:04:18 ◼   ► It's sort of in between the 11 and the max kind of size.

00:04:24 ◼   ► And so it's a pretty big screen.

00:04:27 ◼   ► And you can fit them all in and you can do this great testing.

00:04:30 ◼   ► And it's just a little bit crazy.

00:04:32 ◼   ► And obviously it requires some nice clean separation of your view hierarchy and your

00:04:37 ◼   ► model and you have to be clever with it.

00:04:40 ◼   ► And this is something that you can most use in kind of the early development prototyping

00:04:46 ◼   ► kind of phase where you're developing controls or visualizations or whatever those types

00:04:52 ◼   ► of components that you're going to display ultimately to the user.

00:04:56 ◼   ► This doesn't work great when you're in the final stages of testing.

00:05:00 ◼   ► That gets a bit more tricky there, I'd say.

00:05:01 ◼   ► But this is something that is a tool that I found that is useful.

00:05:04 ◼   ► And if you happen to have an iPhone XR kicking around or an iPhone 11 kicking around, this

00:05:09 ◼   ► is a great little tool for kind of speeding up that initial iteration speed with initial

00:05:15 ◼   ► iPhone development.

00:05:17 ◼   ► Because the build and run cycle connecting to an iPhone is something that is very reliable,

00:05:22 ◼   ► very well tested, and is done over a cable, which I think makes that process even more

00:05:27 ◼   ► straightforward.

00:05:28 ◼   ► It's a pro-tip work around if you find yourself frustrated with on-device testing for the

00:05:33 ◼   ► Apple Watch.

00:05:34 ◼   ► That is awesome.

00:05:35 ◼   ► But I mean, so obviously you can't do watch kit stuff on there.

00:05:39 ◼   ► What kind of views are you testing here?

00:05:41 ◼   ► Just like custom rendered ones?

00:05:43 ◼   ► So a lot of my rendering is custom rendering.

00:05:47 ◼   ► So there's many controls that I have or things that I'm rendering.

00:05:50 ◼   ► An example of this is complications, for example.

00:05:53 ◼   ► Like a lot of the complications that I do, I've at this point, I've essentially re-implemented

00:05:56 ◼   ► Clock Kit.

00:05:58 ◼   ► I have my own version of Clock Kit that I use for development, which I also need for

00:06:04 ◼   ► on the iPhone side of my apps where I'm doing configuration where you say, "Oh, I wanted

00:06:10 ◼   ► to use this font or this color or whatever."

00:06:12 ◼   ► If I make configuration options available, I need a way of previewing that on the iPhone,

00:06:18 ◼   ► which meant I had to write a Clock Kit proxy that essentially simulates the rendering that

00:06:23 ◼   ► you would see in Clock Kit on the device because I have to simulate that in the iPhone app

00:06:28 ◼   ► anyway.

00:06:29 ◼   ► So if I've taken a lot of that code and then just moved it over into ways that I can preview

00:06:33 ◼   ► that, and you also get the advantage with that of things like I have one of my complication

00:06:37 ◼   ► testing systems where I have the complication setups for each of the different watch sizes,

00:06:42 ◼   ► and then at the bottom I can have a slider that moves back and forth in time, for example.

00:06:48 ◼   ► And so if I'm doing a complication that's supposed to change during the day, I can ask

00:06:52 ◼   ► it to give me what the complication should look like at noon, at 1 p.m., at 2 p.m., and

00:06:58 ◼   ► I can just slide the slider back and forth and have it keep updating its rendering dynamically

00:07:03 ◼   ► through that.

00:07:04 ◼   ► And so that's a great way to kind of quickly sanity check, make sure it's working correctly,

00:07:08 ◼   ► dealing with are there weird edge cases or bugs that I need to deal with where if some

00:07:14 ◼   ► of my complications involve shrinking things down to make it fit.

00:07:19 ◼   ► Say like you have a weather complication that displays the temperature.

00:07:23 ◼   ► If the temperature could be one digit, it's three degrees, or it could be 125 degrees.

00:07:30 ◼   ► And given the size of complication controls, like making sure that it works well between

00:07:36 ◼   ► those two, it can sometimes be difficult.

00:07:38 ◼   ► So having, in the same way I can have the iPhone app cycle through all the possible

00:07:42 ◼   ► temperatures or all those types of things, and it's done on doing it on sort of an iPhone

00:07:46 ◼   ► test harness makes this process a lot more efficient for me.

00:07:49 ◼   ► - That's really interesting.

00:07:50 ◼   ► I mean, and I think there's a lot of value in kind of like, in test harnesses that take

00:07:56 ◼   ► some kind of critical code out of the kind of locked down or cumbersome environment it

00:08:03 ◼   ► usually runs in, like whether it's iPhone or watch or whatever else.

00:08:06 ◼   ► Like I think most people listening to the show are iOS developers, obviously.

00:08:10 ◼   ► But it can really help to take things out and put them on the Mac, for instance.

00:08:13 ◼   ► So this is one area that I have been, that helped me a lot, is whenever I'm developing

00:08:20 ◼   ► a new audio thing for Overcast in recent years, I always make a command line version of it

00:08:26 ◼   ► for the Mac that I can test, as long as it doesn't use iOS specific frameworks, which

00:08:31 ◼   ► all my new stuff mostly doesn't.

00:08:33 ◼   ► And so, like Voice Boost 2, again, I've been working on Voice Boost 2 for a long time,

00:08:38 ◼   ► and it's basically audio processing algorithms.

00:08:41 ◼   ► And they're all written in code that is available on the Mac as well.

00:08:44 ◼   ► Like the only, they don't do almost anything with the audio APIs on the Apple platforms.

00:08:50 ◼   ► They're really only doing the accelerate functions, which are available on both.

00:08:54 ◼   ► And so I have this whole Voice Boost test harness program, and as I'm developing it,

00:08:59 ◼   ► I'm tweaking things, and I'm able to, not only does it help for the shortening the cycle,

00:09:04 ◼   ► like the build and run cycle, 'cause I mean, you think it's good going from the watch to

00:09:08 ◼   ► the phone.

00:09:09 ◼   ► Try going directly to your Mac.

00:09:11 ◼   ► It's like another order of magnitude better when it's just build and run, and it makes

00:09:16 ◼   ► a binary, and you have terminal in there, you can just run it right there, and run it

00:09:19 ◼   ► on a whole bunch of files automatically.

00:09:21 ◼   ► So like, I have a different script that checks the Overcast database for the thousand most

00:09:28 ◼   ► popular podcasts, and just downloads their most recent episodes with their ID numbers.

00:09:33 ◼   ► And then I can then have this great sample of very popular podcasts across a pretty wide

00:09:40 ◼   ► range, and I can then run this on all of them to see, like for instance, will this crash?

00:09:45 ◼   ► Will the algorithm have any crashes or memory problems on any particular popular podcast?

00:09:51 ◼   ► And it's good to know that.

00:09:53 ◼   ► And by having this be a Mac command line thing, even though I'm probably never gonna release

00:09:58 ◼   ► the command line utility, it's mostly just a test harness for my iOS app, it still really

00:10:04 ◼   ► helps to have that just for both, for rapid development cycling, and then also in this

00:10:11 ◼   ► context, I'm doing audio processing, it really helps to take the audio input, process it

00:10:17 ◼   ► through Voice Boost 2, and then open up the output that Voice Boost 2 generated in an

00:10:22 ◼   ► audio editor, like Adobe Audition, which is what I use for this.

00:10:24 ◼   ► And then I can analyze what it did to the waveforms, and I can generate graphs, and

00:10:28 ◼   ► I can generate images, and stuff like that, that's just way more, that would be way too

00:10:33 ◼   ► cumbersome to do in an iOS app, even in a simulator.

00:10:37 ◼   ► Like, it's so much easier to have that just be like a Mac command line thing that I can

00:10:41 ◼   ► run.

00:10:42 ◼   ► And then I can run it on those thousand podcasts, and every time I change something about how

00:10:46 ◼   ► memory works, I can make sure I'm not generating a crash by doing like a huge parallel test

00:10:52 ◼   ► run of all this stuff.

00:10:53 ◼   ► I know this is getting a little bit close to test-driven development, I'm sorry, but

00:10:56 ◼   ► I know I'm just kind of like approximating it poorly instead of doing it right.

00:11:01 ◼   ► You're doing a very imperative, practical version of test-driven development.

00:11:05 ◼   ► Yeah.

00:11:06 ◼   ► It's like, you just run your code on lots and lots of things, and see what happens.

00:11:12 ◼   ► I very strongly believe in that kind of like test harness philosophy.

00:11:15 ◼   ► It's hard for a lot of things.

00:11:17 ◼   ► If you are writing WatchKit UI code, for instance, that's going to be pretty hard to take out

00:11:23 ◼   ► of WatchOS, and to try to simulate elsewhere.

00:11:27 ◼   ► I mean, knowing you, you probably could implement WatchKit.

00:11:29 ◼   ► There's only like 10 or 12 controls.

00:11:33 ◼   ► How hard could it be?

00:11:34 ◼   ► That's true.

00:11:35 ◼   ► How hard could it be?

00:11:36 ◼   ► It certainly seems like there aren't a lot of people working on an Apple.

00:11:40 ◼   ► But yeah, so obviously in certain contexts, it's harder than others.

00:11:44 ◼   ► But where possible, where you have something that's isolatable and that you can bring out

00:11:48 ◼   ► into a test harness that makes your job easier, that's a pretty solid thing to do.

00:11:52 ◼   ► Yeah.

00:11:53 ◼   ► And in this case, it's like finding sort of hardware that can simulate something that

00:11:58 ◼   ► you're trying to do, which in your case, like a Mac can do this just fine, or in my case,

00:12:02 ◼   ► finding the right iPhone to use for this is like a great place to sort of run your harnesses

00:12:06 ◼   ► to get a good sense of things.

00:12:08 ◼   ► Exactly.

00:12:09 ◼   ► We are sponsored this week by Linode.

00:12:11 ◼   ► With Linode, you can instantly deploy and manage an SSD server in the Linode cloud.

00:12:15 ◼   ► Actually, I could even run this.

00:12:17 ◼   ► Oh no, I can't do it on Linux, but I could.

00:12:19 ◼   ► I wonder if anybody has the accelerate function.

00:12:22 ◼   ► Anyway, you can instantly deploy and manage an SSD server with Linode in the Linode cloud.

00:12:26 ◼   ► You can get a server running in just seconds with your choice of Linux distro resources

00:12:29 ◼   ► and node location.

00:12:30 ◼   ► I got a bunch of Linode servers and I just love them.

00:12:33 ◼   ► They're so good.

00:12:34 ◼   ► It's such a great host to be with.

00:12:36 ◼   ► It's so easy.

00:12:37 ◼   ► It's such a great value.

00:12:38 ◼   ► I've been with them forever, since long before they were a sponsor because they're just really

00:12:41 ◼   ► good.

00:12:42 ◼   ► They have hundreds of thousands of other customers, so I know I'm not just crazy.

00:12:46 ◼   ► All of us are looked after by their incredible 24/7 support team.

00:12:49 ◼   ► If you ever have any problems, just email them or call them or chat over IRC in the

00:12:53 ◼   ► Linode community if that's easier for you, whatever suits you best.

00:12:56 ◼   ► They have also amazing guides and support documentation, so if you need to quickly look

00:13:01 ◼   ► something up or if you're new to a certain area of Linux system administration, their

00:13:04 ◼   ► documentation is fantastic.

00:13:06 ◼   ► You don't even have to be a customer to see it, but it's just amazing working with Linode.

00:13:11 ◼   ► They also now have a new management panel, cloud.linode.com.

00:13:15 ◼   ► It's a single page app built using the cutting edge ReactJS stack and is backed entirely

00:13:19 ◼   ► by their public API and it's open source too.

00:13:23 ◼   ► So anything you can do in the control panel, you can also do with their API if you want

00:13:26 ◼   ► to script things or automate things.

00:13:28 ◼   ► They also have two-factor authentication to keep you and all your data safe and secure.

00:13:32 ◼   ► So check it out today.

00:13:33 ◼   ► They have pricing options to suit everyone, starting at plans with just one gig of RAM

00:13:37 ◼   ► for just $5 a month.

00:13:39 ◼   ► You can do a lot with a one gig of RAM server and five bucks a month.

00:13:42 ◼   ► I mean, that's basically nothing.

00:13:44 ◼   ► And they also have, of course, all sorts of things above and beyond that for whatever

00:13:47 ◼   ► you need.

00:13:48 ◼   ► And I have been, again, I've been a customer for theirs for almost a decade.

00:13:50 ◼   ► They're always the best value in the business.

00:13:52 ◼   ► I've never found anybody that consistently beats them.

00:13:55 ◼   ► And you can also get $20 towards any Linode plan by going to linode.com/radar and using

00:14:01 ◼   ► promo code radar2019.

00:14:04 ◼   ► So 20 bucks, that could be four months on that one gig plan.

00:14:06 ◼   ► And with a seven-day money-back guarantee, you have nothing to lose.

00:14:09 ◼   ► So give them a try today.

00:14:11 ◼   ► Linode.com/radar, promo code radar2019.

00:14:15 ◼   ► Sign up there and make the most of that $20 credit.

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

00:14:21 ◼   ► So another kind of fun work around, I don't know, hack thing that I've used recently and

00:14:27 ◼   ► I think is a useful tool to keep in the back of your mind when you're especially prototyping,

00:14:30 ◼   ► but even just for actual production work as well, is just how far you can get with just

00:14:37 ◼   ► basic UI views, doing basic UI view animation, and some of the basic kind of core graphics

00:14:44 ◼   ► operations that you can do with UI views.

00:14:46 ◼   ► So for example, in the most recent version of Sleepless Plus and Sleepless Plus 4, I

00:14:52 ◼   ► have a whole bunch of graphs and the really cool sort of data visualizations for how you've

00:14:56 ◼   ► been sleeping.

00:14:58 ◼   ► And I wanted to make these kind of fun and interactive.

00:15:00 ◼   ► And one of them shows you your sort of typical bedtime and typical wakeup time for different

00:15:05 ◼   ► days of the week.

00:15:06 ◼   ► So you can say, you know, when do I typically go to bed on Monday night, Tuesday night,

00:15:09 ◼   ► Wednesday night, et cetera.

00:15:11 ◼   ► And what I wanted was a kind of a nice, fluid, interesting way to transition between the

00:15:16 ◼   ► different displays that I show there.

00:15:19 ◼   ► And what I ended up doing is the graph is, you know, it's a series of bar graphs basically

00:15:23 ◼   ► that are, I guess it's a histogram?

00:15:26 ◼   ► I don't know.

00:15:28 ◼   ► It's a nice graph.

00:15:29 ◼   ► Go look at it and go get Sleepless Plus.

00:15:31 ◼   ► It's a nice graph.

00:15:32 ◼   ► All apologies to Dr. Dering.

00:15:34 ◼   ► But what it, to make it animate fluidly between them, I just make each of the bars a UI view

00:15:39 ◼   ► inside of a parent UI view.

00:15:41 ◼   ► And when you change the data, it just moves the bars from one, it's like from one graph,

00:15:49 ◼   ► from one day to the other.

00:15:50 ◼   ► Like it just does the UI view basic animation and it's just changing the frame of each of

00:15:54 ◼   ► the different bars and it just reuses them so that they animate fluidly between them.

00:15:59 ◼   ► And you get this beautiful, really nice effect of like this nice, rich, smooth, super performant

00:16:05 ◼   ► animation that under the hood is just some UI views with some color.

00:16:09 ◼   ► And if I wanted to do this with like, you know, a lower level API using core graphics

00:16:14 ◼   ► and using CA display links that I could update my animation on a regular basis, like it would

00:16:18 ◼   ► be a lot of pain and suffering.

00:16:20 ◼   ► It turns out you can just, you can just use UI views for your, you know, for your graphical

00:16:26 ◼   ► elements and then just do a, you know, UI view animate with duration, you know, 0.25.

00:16:33 ◼   ► You get the great effect, super straightforward and is really sort of easy to debug and take

00:16:38 ◼   ► a look at because they're just UI views.

00:16:40 ◼   ► They're not, you know, this, this, this sort of opaque representation.

00:16:43 ◼   ► If I was rendering this into an image and then animating it that way or using some kind

00:16:46 ◼   ► of third party graphing framework or charting framework, you know, I'm bringing in a dependency

00:16:51 ◼   ► and some that does a lot more than I probably would want.

00:16:54 ◼   ► Like this is the, the entire graph and sort of the graphing system is a relatively simple,

00:16:59 ◼   ► you know, class, maybe a few hundred lines of code, very performant and straightforward.

00:17:04 ◼   ► So like you can go a long way with UI view animation.

00:17:06 ◼   ► And I think it's a great place to start anytime you wanted to do some kind of rich animation

00:17:11 ◼   ► inside of your applications.

00:17:13 ◼   ► Yeah, I would go even further with that and say like, you know, in general, like try things

00:17:18 ◼   ► that you assume would be too slow, try it first because you'd be surprised what modern

00:17:26 ◼   ► hardware is capable of.

00:17:28 ◼   ► Like again, this is something I've run into constantly with voice boost to development

00:17:31 ◼   ► is like, I kept thinking I would make an assumption like, oh, there's a certain type of processing

00:17:37 ◼   ► that that's pretty sophisticated.

00:17:39 ◼   ► It requires like something like a lot of math for every audio sample.

00:17:43 ◼   ► And you know, you're playing 44,100 samples per second, possibly in two channels.

00:17:48 ◼   ► So two sets of those.

00:17:49 ◼   ► And so like that's, that's a lot of math, you know, possibly having to do like significant

00:17:54 ◼   ► operations on 88,200 samples per second total and trying to do that in a power envelope

00:18:01 ◼   ► that is not going to kill people's battery lives or make their phones hot or get your

00:18:04 ◼   ► app killed.

00:18:05 ◼   ► And ideally, possibly in the future, run on the Apple Watch as well.

00:18:09 ◼   ► And so I would often assume, well, there's a certain kind of processing that I am not

00:18:14 ◼   ► going to be able to do.

00:18:15 ◼   ► You know, like I would write it because I also use voice boost that the aforementioned

00:18:20 ◼   ► command line utility.

00:18:21 ◼   ► I also use it myself for pre-processing my podcast files, just to save myself some time.

00:18:25 ◼   ► And that's why I might someday release it, but it's not on my front of mind, honestly.

00:18:30 ◼   ► For reasons we've talked about on the show before.

00:18:34 ◼   ► And so, but you know, I'd have like, you know, the high quality, like mastering quality algorithm.

00:18:40 ◼   ► And then I would write a low quality one as well, figuring I'd run that on the phone.

00:18:43 ◼   ► And then I'd run it on the phone and I would find that the performance difference really

00:18:47 ◼   ► was not very big and that the mastering algorithm runs totally fine and would be like, you know,

00:18:54 ◼   ► 0.2% of the CPU usage during playback or something.

00:18:58 ◼   ► Like modern hardware is way faster than you might assume it is.

00:19:03 ◼   ► Way faster.

00:19:04 ◼   ► And especially in an area like UI views, where that is something that like Apple puts a lot

00:19:10 ◼   ► of resources, both software and hardware into making sure that kind of stuff is extremely

00:19:16 ◼   ► fast because everything uses it.

00:19:19 ◼   ► And it matters a lot.

00:19:21 ◼   ► Every app uses views and layers and compositing behind the scenes and everything.

00:19:25 ◼   ► Like that's a pretty significant part of the OS and the frameworks.

00:19:28 ◼   ► And the GPUs accelerate everything.

00:19:30 ◼   ► It's a whole thing.

00:19:31 ◼   ► And so you can do so much with that, that like, you know, you don't need to get into

00:19:36 ◼   ► like manual image rendering or dropping down to the metal APIs or anything like that for

00:19:41 ◼   ► almost any reason.

00:19:42 ◼   ► Like you can make a game out of UI views.

00:19:45 ◼   ► You could have 100 UI views on the screen animating around, like bouncing around as

00:19:49 ◼   ► sprites for a game.

00:19:50 ◼   ► It isn't the most performant way to make a game, but you could do it.

00:19:54 ◼   ► And if that's what you know and you're just trying to get something done quickly or you

00:19:58 ◼   ► wouldn't make it otherwise, just do that.

00:20:01 ◼   ► And it's probably fine.

00:20:02 ◼   ► - I think there's a lot of these things where like you can get, yeah, it's like you can

00:20:06 ◼   ► get the proof of concept at least and probably even potentially better than that, just using

00:20:11 ◼   ► UI views.

00:20:12 ◼   ► And then like, you know, and just finding interesting ways or creative ways to use them.

00:20:14 ◼   ► Like another example of something that I found myself doing several times over my career

00:20:18 ◼   ► is applying CA rotation transforms to views.

00:20:23 ◼   ► So say for example, you wanted to have a graph that scrolled horizontally, say like pedometer

00:20:30 ◼   ► plus plus where it has a bar graph for every day and it scrolls horizontally.

00:20:34 ◼   ► What about if you just take a UI table view and rotate it 90 degrees?

00:20:37 ◼   ► - Oh my God, does that actually work?

00:20:39 ◼   ► - It does.

00:20:40 ◼   ► It works fine.

00:20:41 ◼   ► - I love that you've tried that.

00:20:44 ◼   ► - And you just have to see, you apply a rotation to the view and then you apply a rotation

00:20:47 ◼   ► to the sub views to make them so that they're the right way out again.

00:20:52 ◼   ► But it totally works.

00:20:53 ◼   ► And you can do the same thing with a UI picker.

00:20:56 ◼   ► If you want a horizontal picker to be, picker rather than to be vertical, to be horizontal,

00:21:00 ◼   ► you can use a UI picker to do that and make it horizontal.

00:21:04 ◼   ► And like, it's a little bit crazy and it's like, I've also subsequently moved away from

00:21:09 ◼   ► that in pedometer.

00:21:10 ◼   ► Like I've sort of implemented my own kind of version based on UI scroll view, but it

00:21:14 ◼   ► wasn't because the other version didn't work.

00:21:16 ◼   ► It was because I wanted to do more than UI table view could allow me to do.

00:21:20 ◼   ► - I hope that somewhere there's a UI kit engineer listening to this right now and either fist

00:21:26 ◼   ► pumping because they put in the work to make that work or crying that you're horribly abusing

00:21:33 ◼   ► their API.

00:21:34 ◼   ► - Well, but I think it's like, it is a great, it's like those are the kinds of little tools

00:21:37 ◼   ► that I'm thinking of sometimes where it's like, there's UI kit is such a rich and like,

00:21:44 ◼   ► well like sort of battle tested, well written piece of software that like you can do weird

00:21:49 ◼   ► stuff with it.

00:21:50 ◼   ► It'll probably work like you kind of would hope it would.

00:21:53 ◼   ► And you'll have some weird quirks to work around maybe, but like you can do a lot with

00:21:57 ◼   ► this kind of stuff.

00:21:58 ◼   ► And like many of these kinds of things, like in this case, the right answer is to use a

00:22:02 ◼   ► UI collection view now rather than a UI table view.

00:22:06 ◼   ► But like you can go a long way with just being thoughtful with like, huh, what if I applied

00:22:11 ◼   ► a, you know, what if I applied a transform to a UI view or just, like you're saying,

00:22:18 ◼   ► create lots of different views or put views inside of views and like UI kit can handle

00:22:24 ◼   ► most of this without a performance issue, without a problem.

00:22:28 ◼   ► And it's the best way that I've found to do that first draft of an app.

00:22:32 ◼   ► And sometimes that first draft becomes the final draft.

00:22:35 ◼   ► But even if it doesn't, it's a really amazing, like the best prototyping tool I found at

00:22:40 ◼   ► this point is UI kit.

00:22:41 ◼   ► Like beyond doing some kind of like prototyping framework, like these things that you, you

00:22:45 ◼   ► know, there's tools that you can do where you are like using some kind of other tool.

00:22:48 ◼   ► It's like, no, just use UI views and it'll be fine.

00:22:50 ◼   ► - Yeah, I mean, like I think a lot of this wisdom comes down to like don't assume something

00:22:55 ◼   ► won't work unless you've actually tried it.

00:22:58 ◼   ► Like something that sounds like it shouldn't work, like rotating a table view 90 degrees

00:23:01 ◼   ► with a transform to make a horizontal table view.

00:23:04 ◼   ► Oh, it's so funny to me.

00:23:06 ◼   ► But like, you know, just try it.

00:23:08 ◼   ► Like, and I think most of us, myself included, wouldn't have thought to ever even try that.

00:23:14 ◼   ► And that's why like people like you who think outside the box, like that's kind of literally

00:23:17 ◼   ► what that means.

00:23:18 ◼   ► Like, you're just like, hey, this crazy hack might work.

00:23:22 ◼   ► Let's see if it does work.

00:23:24 ◼   ► - And like appreciate, I think, come to those types of situations with the humility to say

00:23:29 ◼   ► this is a hack and I need to keep that in mind and not just like, oh, it sort of works.

00:23:33 ◼   ► Like, no, you need to test it.

00:23:34 ◼   ► You need to be a bit more thorough with it, but like try it.

00:23:36 ◼   ► What's it going to hurt?

00:23:37 ◼   ► And like if you can end up with this really, you know, super easy way of doing this and

00:23:42 ◼   ► it's doing all the caching and memory performance and all these huge benefits that you might

00:23:46 ◼   ► be able to get from using one of the pre-built controls just by tweaking it slightly or transforming

00:23:51 ◼   ► it in some way.

00:23:52 ◼   ► Like, you can go a long way with that.

00:23:54 ◼   ► - That's amazing.

00:23:55 ◼   ► - The other kind of interesting thing that I've been doing recently that I just kind

00:23:58 ◼   ► of wanted to mention is the way that some kind of tools and things for localization

00:24:03 ◼   ► of apps.

00:24:05 ◼   ► And so first, the one thing I wanted to point out, and this was something that I only recently

00:24:08 ◼   ► discovered, is in iOS 13, we now have per app language settings as one of the options.

00:24:16 ◼   ► So if you go to the settings app, scroll down to an application, and it supports localization,

00:24:20 ◼   ► you can override the system language for just that application, which is a tremendous tool

00:24:27 ◼   ► for development and debugging and testing because you can now very easily and in a very

00:24:33 ◼   ► lightweight way change the language of just your application.

00:24:36 ◼   ► So I can be like, what does my app look like in German?

00:24:39 ◼   ► What does my app look like in French?

00:24:40 ◼   ► What does my app look like in Spanish?

00:24:42 ◼   ► And I can make those changes very quickly, and it doesn't change the whole system, whereas

00:24:47 ◼   ► previously I would have the rather amusing situation where, especially in the non-Roman

00:24:53 ◼   ► alphabet languages where I would change the system language into Chinese simplified or

00:24:58 ◼   ► Korean or Japanese, and then I have to remember the steps in the settings app that I need

00:25:03 ◼   ► to use to go back to the changed language screen and change it back into English, but

00:25:09 ◼   ► I have to do it just by memory of it's the fourth item down, then it's the second item

00:25:14 ◼   ► down, and then I scroll through this.

00:25:17 ◼   ► It's great to just be able to do it, keep the system language as English, and just change

00:25:21 ◼   ► the language on a per app basis.

00:25:23 ◼   ► So that is a great little tool both for generating screenshots, for helping debug problems with

00:25:28 ◼   ► customers, which is how this actually first came to my attention, was it's like there

00:25:32 ◼   ► were customers who had issues in a particular language or had a problem, and it's like I

00:25:36 ◼   ► can easily, much more easily, get them a screenshot or understand what it is they're seeing by

00:25:41 ◼   ► just changing it for the app.

00:25:42 ◼   ► So pro tip one.

00:25:44 ◼   ► And pro tip two is just something that I, it's like it's one of those things where I'm

00:25:50 ◼   ► not sure this is a recommendation so much as just an observation of something that I've

00:25:54 ◼   ► done in the past.

00:25:56 ◼   ► So often when I'm doing localization, there will be like one line of text that needs to

00:26:00 ◼   ► be updated for the purpose of a update, and it's only one line, and I don't really want

00:26:05 ◼   ► to go through the fuss of doing the, like going through a localization service and getting

00:26:11 ◼   ► it translated and then incorporating it and hoping that the translator understood the

00:26:15 ◼   ► nuance of what I meant in this particular case.

00:26:20 ◼   ► And so something that I've done many times, which I'm not sure is a recommendation, but

00:26:23 ◼   ► it's certainly something to keep in mind, is I think of a string that iOS uses inside

00:26:29 ◼   ► of its own apps.

00:26:32 ◼   ► So the apps that Apple ships or in iOS itself, and I will essentially just copy whatever

00:26:39 ◼   ► it is that they used as their string for a particular localization.

00:26:45 ◼   ► So as an example, when I was implementing the system-wide dark mode in Podometer++,

00:26:50 ◼   ► one of the things that I needed was a string that basically said, "Do you want to use the

00:26:56 ◼   ► setting that you set as an override inside of Podometer, or should it just use the system,

00:27:00 ◼   ► or should it just mirror the system setting?"

00:27:03 ◼   ► Was basically what I needed a toggle switch to have.

00:27:08 ◼   ► Many of us have had this toggle switch implemented in the last few months.

00:27:13 ◼   ► But I remember that in the Watch Companion app, in the Notifications Settings area, one

00:27:19 ◼   ► of the options is "Mirror My iPhone," which is an option that you can have, "Do you want

00:27:26 ◼   ► the notification settings to mirror the iPhone settings, or do you want custom settings?"

00:27:31 ◼   ► And so what I did is I just went through and changed my phone to be in German, in French,

00:27:38 ◼   ► in Spanish, etc., and I just copied down what Apple had translated "Mirror My iPhone" to

00:27:46 ◼   ► into those different languages, which should capture the nuance of what it is I'm trying

00:27:49 ◼   ► to do, because it's the same concept.

00:27:51 ◼   ► I'm not talking about mirror in terms of the glass thing that you look at, and it

00:27:56 ◼   ► reflects back on you.

00:27:57 ◼   ► If I had just used a localization service, you could potentially imagine there's a nuance

00:28:01 ◼   ► that is lost there.

00:28:03 ◼   ► This is a very hard thing to write copy for, even in your own language.

00:28:08 ◼   ► And so I was like, "I'll just copy Apple's."

00:28:10 ◼   ► And there's a few times that I have to go to Google Translate to work out, "I'll put

00:28:14 ◼   ► in the English and then I'll translate into the language and try a few words."

00:28:18 ◼   ► Sometimes it's hard to copy, especially in a language that doesn't use the Roman alphabet,

00:28:25 ◼   ► but I was able to eventually play around with, "Is it mirror?

00:28:29 ◼   ► Is it copy?

00:28:30 ◼   ► Is it whatever?"

00:28:31 ◼   ► You get to try a bunch of different synonyms, and eventually you get the character that

00:28:36 ◼   ► matches the character you're looking for.

00:28:38 ◼   ► And that's what I used.

00:28:39 ◼   ► And like I said, not necessarily recommended, not great in some ways, because obviously

00:28:43 ◼   ► I'm assuming that meaning translates, but so far it's worked.

00:28:48 ◼   ► No, I'm going to say that's great.

00:28:50 ◼   ► I'm going to override you in that and say that is an awesome hack, because copywriting

00:28:55 ◼   ► is something that Apple does very well in the UIs.

00:28:58 ◼   ► And it's one of the hardest things to do in an app, especially if you're trying to outsource

00:29:03 ◼   ► it to a language that you don't know, so you kind of can't check.

00:29:06 ◼   ► So that's actually an awesome hack, because whatever Apple figured for their localizations

00:29:10 ◼   ► is not only saving you time, it's probably better than anything you would have gotten

00:29:13 ◼   ► back.

00:29:14 ◼   ► Yeah.

00:29:15 ◼   ► So anyway, it's just a fun little thing that if you can think of a place or structuring

00:29:19 ◼   ► your copy so that it matches Apple's copy, you can save yourself a lot of time.

00:29:23 ◼   ► And apparently, according to you, it's even better.

00:29:26 ◼   ► So I'll take that and recommend it now as a way to speed up your localization process,

00:29:33 ◼   ► especially for kind of simple things.

00:29:35 ◼   ► And I suppose you could also use it to validate externally produced localizations.

00:29:38 ◼   ► You could take that approach as well if you wanted to go that way.

00:29:40 ◼   ► But either way, fun little trick.

00:29:42 ◼   ► That's awesome.

00:29:43 ◼   ► Thanks for listening, everybody.

00:29:44 ◼   ► And we'll talk to you in two weeks.

00:29:46 ◼   ► Bye.

00:29:47 ◼   ► [BLANK_AUDIO]