0:00:00Welcome to Under the Radar, a show about independent iOS app development.
0:00:04I'm Marco Arment.
0:00:05And I'm David Smith.
0:00:06Under the Radar is never longer than 30 minutes, so let's get started.
0:00:10So today's episode is going to be kind of in the...
0:00:15If we were a news website, this would be the article with the title like "Seven Crazy Hacks
0:00:21That You Won't Believe."
0:00:23Or more practically, this is the...
0:00:26I've been thinking a lot about kind of weird or interesting workarounds or approaches I've
0:00:30been taking to work around either limitations in the platform or just things that I do on
0:00:36a regular basis to make my development process more efficient, more straightforward, and
0:00:42ultimately in a lot of ways just more sane.
0:00:45That these are little things or tweaks or things that I've done that I've just found
0:00:49make my life a little bit easier.
0:00:50And I think that it's like whenever I find these things, I feel like they're useful and
0:00:53worthwhile sharing because maybe they can make...
0:00:56Maybe they're very specific to my situation, but my situation is probably somewhat similar
0:01:01to at least some other developers out there, so it seems worth sharing.
0:01:06So the first one of these, and just to get the flavor of the kind of thing I'm talking
0:01:09about is...
0:01:10So developing for the Apple Watch is something that is the actual on-device testing and working
0:01:17with that is something that I find very cumbersome is probably the kind way to say that.
0:01:22That's an understatement of the year right there.
0:01:25So it is like actually getting your app to transfer over to the watch, have it launched,
0:01:31have it debug correctly and successfully.
0:01:33All of those things are just...
0:01:36It's just cumbersome.
0:01:37And that's just sort of in some ways inherent in it being a wireless debugging session and
0:01:41there's lots of complexity around that.
0:01:43It's going via your phone and it's getting better, but it's still not great.
0:01:47But I find that the nature of watch development requires a certain degree of on-device testing
0:01:56to really be checking and looking at things, because it's such a small screen that if I
0:02:02spend too much time just in the simulator on my Mac, I don't get a great sense of how
0:02:07things would actually work in practice, how big a button would be, how legible some text
0:02:12would be in practice.
0:02:13And this is sort of magnified by dealing with the fact that you have even small and relatively
0:02:21large Apple Watch screen sizes going from the 44mm series 4 and 5 to the 38mm series
0:02:273.
0:02:28There's a pretty wide range in size there.
0:02:31And this was something that was causing me a lot of difficulty, and so I kind of cast
0:02:33around trying to come up with a reasonable solution.
0:02:36And what I ended up with was something that I thought was kind of interesting.
0:02:39So the screen resolution, or the screen DPI, pixel density of the Apple Watch is 326 DPI.
0:02:48This is an OLED screen and it's rendered at 2x, which turns out to be very similar to
0:02:54the iPhone XR and 11, which are also 326 DPI, 2x, their LCD rather than OLED.
0:03:02So there's certainly a difference there.
0:03:04Which has then led me to a place where I now, for a lot of my visual development for Apple
0:03:10Watch, have built these kind of weird test harnesses where I take my UI as I expect to
0:03:18render it for the Apple Watch and render it instead on a XR that I have kicking around.
0:03:25And I can get a great sense of how things appear visually, how they work on different
0:03:29screen sizes, how anything other than probably color, because color is going to be a bit
0:03:34tricky, either most different between those two technologies.
0:03:37But general physical size and legibility are more similar.
0:03:40And I found this to be a great tool for this.
0:03:42And I use a XR rather than the older, there's several older iPhones that also had 326 DPI,
0:03:472x screens.
0:03:48I think all of them from the iPhone 4 forward?
0:03:51Probably.
0:03:52But the great thing about the XR is its screen is large enough that you can actually fit
0:03:56all four of the Apple Watch screen sizes on a XR screen.
0:04:01That's awesome.
0:04:02Currently.
0:04:03So you have all the watch sizes on a phone at the exact right physical sizes so you can
0:04:09test the interactivity and whether the stuff is too small and everything?
0:04:13Roughly, yeah.
0:04:14That's awesome.
0:04:15That is basically what you can do.
0:04:16Because the XR screen is actually pretty big.
0:04:18It's sort of in between the 11 and the max kind of size.
0:04:24And so it's a pretty big screen.
0:04:27And you can fit them all in and you can do this great testing.
0:04:30And it's just a little bit crazy.
0:04:32And obviously it requires some nice clean separation of your view hierarchy and your
0:04:37model and you have to be clever with it.
0:04:40And this is something that you can most use in kind of the early development prototyping
0:04:46kind of phase where you're developing controls or visualizations or whatever those types
0:04:52of components that you're going to display ultimately to the user.
0:04:56This doesn't work great when you're in the final stages of testing.
0:05:00That gets a bit more tricky there, I'd say.
0:05:01But this is something that is a tool that I found that is useful.
0:05:04And if you happen to have an iPhone XR kicking around or an iPhone 11 kicking around, this
0:05:09is a great little tool for kind of speeding up that initial iteration speed with initial
0:05:15iPhone development.
0:05:17Because the build and run cycle connecting to an iPhone is something that is very reliable,
0:05:22very well tested, and is done over a cable, which I think makes that process even more
0:05:27straightforward.
0:05:28It's a pro-tip work around if you find yourself frustrated with on-device testing for the
0:05:33Apple Watch.
0:05:34That is awesome.
0:05:35But I mean, so obviously you can't do watch kit stuff on there.
0:05:39What kind of views are you testing here?
0:05:41Just like custom rendered ones?
0:05:43So a lot of my rendering is custom rendering.
0:05:47So there's many controls that I have or things that I'm rendering.
0:05:50An example of this is complications, for example.
0:05:53Like a lot of the complications that I do, I've at this point, I've essentially re-implemented
0:05:56Clock Kit.
0:05:58I have my own version of Clock Kit that I use for development, which I also need for
0:06:04on the iPhone side of my apps where I'm doing configuration where you say, "Oh, I wanted
0:06:10to use this font or this color or whatever."
0:06:12If I make configuration options available, I need a way of previewing that on the iPhone,
0:06:18which meant I had to write a Clock Kit proxy that essentially simulates the rendering that
0:06:23you would see in Clock Kit on the device because I have to simulate that in the iPhone app
0:06:28anyway.
0:06:29So if I've taken a lot of that code and then just moved it over into ways that I can preview
0:06:33that, and you also get the advantage with that of things like I have one of my complication
0:06:37testing systems where I have the complication setups for each of the different watch sizes,
0:06:42and then at the bottom I can have a slider that moves back and forth in time, for example.
0:06:48And so if I'm doing a complication that's supposed to change during the day, I can ask
0:06:52it to give me what the complication should look like at noon, at 1 p.m., at 2 p.m., and
0:06:58I can just slide the slider back and forth and have it keep updating its rendering dynamically
0:07:03through that.
0:07:04And so that's a great way to kind of quickly sanity check, make sure it's working correctly,
0:07:08dealing with are there weird edge cases or bugs that I need to deal with where if some
0:07:14of my complications involve shrinking things down to make it fit.
0:07:19Say like you have a weather complication that displays the temperature.
0:07:23If the temperature could be one digit, it's three degrees, or it could be 125 degrees.
0:07:30And given the size of complication controls, like making sure that it works well between
0:07:36those two, it can sometimes be difficult.
0:07:38So having, in the same way I can have the iPhone app cycle through all the possible
0:07:42temperatures or all those types of things, and it's done on doing it on sort of an iPhone
0:07:46test harness makes this process a lot more efficient for me.
0:07:49- That's really interesting.
0:07:50I mean, and I think there's a lot of value in kind of like, in test harnesses that take
0:07:56some kind of critical code out of the kind of locked down or cumbersome environment it
0:08:03usually runs in, like whether it's iPhone or watch or whatever else.
0:08:06Like I think most people listening to the show are iOS developers, obviously.
0:08:10But it can really help to take things out and put them on the Mac, for instance.
0:08:13So this is one area that I have been, that helped me a lot, is whenever I'm developing
0:08:20a new audio thing for Overcast in recent years, I always make a command line version of it
0:08:26for the Mac that I can test, as long as it doesn't use iOS specific frameworks, which
0:08:31all my new stuff mostly doesn't.
0:08:33And so, like Voice Boost 2, again, I've been working on Voice Boost 2 for a long time,
0:08:38and it's basically audio processing algorithms.
0:08:41And they're all written in code that is available on the Mac as well.
0:08:44Like the only, they don't do almost anything with the audio APIs on the Apple platforms.
0:08:50They're really only doing the accelerate functions, which are available on both.
0:08:54And so I have this whole Voice Boost test harness program, and as I'm developing it,
0:08:59I'm tweaking things, and I'm able to, not only does it help for the shortening the cycle,
0:09:04like the build and run cycle, 'cause I mean, you think it's good going from the watch to
0:09:08the phone.
0:09:09Try going directly to your Mac.
0:09:11It's like another order of magnitude better when it's just build and run, and it makes
0:09:16a binary, and you have terminal in there, you can just run it right there, and run it
0:09:19on a whole bunch of files automatically.
0:09:21So like, I have a different script that checks the Overcast database for the thousand most
0:09:28popular podcasts, and just downloads their most recent episodes with their ID numbers.
0:09:33And then I can then have this great sample of very popular podcasts across a pretty wide
0:09:40range, and I can then run this on all of them to see, like for instance, will this crash?
0:09:45Will the algorithm have any crashes or memory problems on any particular popular podcast?
0:09:51And it's good to know that.
0:09:53And by having this be a Mac command line thing, even though I'm probably never gonna release
0:09:58the command line utility, it's mostly just a test harness for my iOS app, it still really
0:10:04helps to have that just for both, for rapid development cycling, and then also in this
0:10:11context, I'm doing audio processing, it really helps to take the audio input, process it
0:10:17through Voice Boost 2, and then open up the output that Voice Boost 2 generated in an
0:10:22audio editor, like Adobe Audition, which is what I use for this.
0:10:24And then I can analyze what it did to the waveforms, and I can generate graphs, and
0:10:28I can generate images, and stuff like that, that's just way more, that would be way too
0:10:33cumbersome to do in an iOS app, even in a simulator.
0:10:37Like, it's so much easier to have that just be like a Mac command line thing that I can
0:10:41run.
0:10:42And then I can run it on those thousand podcasts, and every time I change something about how
0:10:46memory works, I can make sure I'm not generating a crash by doing like a huge parallel test
0:10:52run of all this stuff.
0:10:53I know this is getting a little bit close to test-driven development, I'm sorry, but
0:10:56I know I'm just kind of like approximating it poorly instead of doing it right.
0:11:01You're doing a very imperative, practical version of test-driven development.
0:11:05Yeah.
0:11:06It's like, you just run your code on lots and lots of things, and see what happens.
0:11:12I very strongly believe in that kind of like test harness philosophy.
0:11:15It's hard for a lot of things.
0:11:17If you are writing WatchKit UI code, for instance, that's going to be pretty hard to take out
0:11:23of WatchOS, and to try to simulate elsewhere.
0:11:27I mean, knowing you, you probably could implement WatchKit.
0:11:29There's only like 10 or 12 controls.
0:11:33How hard could it be?
0:11:34That's true.
0:11:35How hard could it be?
0:11:36It certainly seems like there aren't a lot of people working on an Apple.
0:11:40But yeah, so obviously in certain contexts, it's harder than others.
0:11:44But where possible, where you have something that's isolatable and that you can bring out
0:11:48into a test harness that makes your job easier, that's a pretty solid thing to do.
0:11:52Yeah.
0:11:53And in this case, it's like finding sort of hardware that can simulate something that
0:11:58you're trying to do, which in your case, like a Mac can do this just fine, or in my case,
0:12:02finding the right iPhone to use for this is like a great place to sort of run your harnesses
0:12:06to get a good sense of things.
0:12:08Exactly.
0:12:09We are sponsored this week by Linode.
0:12:11With Linode, you can instantly deploy and manage an SSD server in the Linode cloud.
0:12:15Actually, I could even run this.
0:12:17Oh no, I can't do it on Linux, but I could.
0:12:19I wonder if anybody has the accelerate function.
0:12:22Anyway, you can instantly deploy and manage an SSD server with Linode in the Linode cloud.
0:12:26You can get a server running in just seconds with your choice of Linux distro resources
0:12:29and node location.
0:12:30I got a bunch of Linode servers and I just love them.
0:12:33They're so good.
0:12:34It's such a great host to be with.
0:12:36It's so easy.
0:12:37It's such a great value.
0:12:38I've been with them forever, since long before they were a sponsor because they're just really
0:12:41good.
0:12:42They have hundreds of thousands of other customers, so I know I'm not just crazy.
0:12:46All of us are looked after by their incredible 24/7 support team.
0:12:49If you ever have any problems, just email them or call them or chat over IRC in the
0:12:53Linode community if that's easier for you, whatever suits you best.
0:12:56They have also amazing guides and support documentation, so if you need to quickly look
0:13:01something up or if you're new to a certain area of Linux system administration, their
0:13:04documentation is fantastic.
0:13:06You don't even have to be a customer to see it, but it's just amazing working with Linode.
0:13:11They also now have a new management panel, cloud.linode.com.
0:13:15It's a single page app built using the cutting edge ReactJS stack and is backed entirely
0:13:19by their public API and it's open source too.
0:13:23So anything you can do in the control panel, you can also do with their API if you want
0:13:26to script things or automate things.
0:13:28They also have two-factor authentication to keep you and all your data safe and secure.
0:13:32So check it out today.
0:13:33They have pricing options to suit everyone, starting at plans with just one gig of RAM
0:13:37for just $5 a month.
0:13:39You can do a lot with a one gig of RAM server and five bucks a month.
0:13:42I mean, that's basically nothing.
0:13:44And they also have, of course, all sorts of things above and beyond that for whatever
0:13:47you need.
0:13:48And I have been, again, I've been a customer for theirs for almost a decade.
0:13:50They're always the best value in the business.
0:13:52I've never found anybody that consistently beats them.
0:13:55And you can also get $20 towards any Linode plan by going to linode.com/radar and using
0:14:01promo code radar2019.
0:14:04So 20 bucks, that could be four months on that one gig plan.
0:14:06And with a seven-day money-back guarantee, you have nothing to lose.
0:14:09So give them a try today.
0:14:11Linode.com/radar, promo code radar2019.
0:14:15Sign up there and make the most of that $20 credit.
0:14:17Our thanks to Linode for their support of this show and all of Relay FM.
0:14:21So another kind of fun work around, I don't know, hack thing that I've used recently and
0:14:27I think is a useful tool to keep in the back of your mind when you're especially prototyping,
0:14:30but even just for actual production work as well, is just how far you can get with just
0:14:37basic UI views, doing basic UI view animation, and some of the basic kind of core graphics
0:14:44operations that you can do with UI views.
0:14:46So for example, in the most recent version of Sleepless Plus and Sleepless Plus 4, I
0:14:52have a whole bunch of graphs and the really cool sort of data visualizations for how you've
0:14:56been sleeping.
0:14:58And I wanted to make these kind of fun and interactive.
0:15:00And one of them shows you your sort of typical bedtime and typical wakeup time for different
0:15:05days of the week.
0:15:06So you can say, you know, when do I typically go to bed on Monday night, Tuesday night,
0:15:09Wednesday night, et cetera.
0:15:11And what I wanted was a kind of a nice, fluid, interesting way to transition between the
0:15:16different displays that I show there.
0:15:19And what I ended up doing is the graph is, you know, it's a series of bar graphs basically
0:15:23that are, I guess it's a histogram?
0:15:26I don't know.
0:15:28It's a nice graph.
0:15:29Go look at it and go get Sleepless Plus.
0:15:31It's a nice graph.
0:15:32All apologies to Dr. Dering.
0:15:34But what it, to make it animate fluidly between them, I just make each of the bars a UI view
0:15:39inside of a parent UI view.
0:15:41And when you change the data, it just moves the bars from one, it's like from one graph,
0:15:49from one day to the other.
0:15:50Like it just does the UI view basic animation and it's just changing the frame of each of
0:15:54the different bars and it just reuses them so that they animate fluidly between them.
0:15:59And you get this beautiful, really nice effect of like this nice, rich, smooth, super performant
0:16:05animation that under the hood is just some UI views with some color.
0:16:09And if I wanted to do this with like, you know, a lower level API using core graphics
0:16:14and using CA display links that I could update my animation on a regular basis, like it would
0:16:18be a lot of pain and suffering.
0:16:20It turns out you can just, you can just use UI views for your, you know, for your graphical
0:16:26elements and then just do a, you know, UI view animate with duration, you know, 0.25.
0:16:33You get the great effect, super straightforward and is really sort of easy to debug and take
0:16:38a look at because they're just UI views.
0:16:40They're not, you know, this, this, this sort of opaque representation.
0:16:43If I was rendering this into an image and then animating it that way or using some kind
0:16:46of third party graphing framework or charting framework, you know, I'm bringing in a dependency
0:16:51and some that does a lot more than I probably would want.
0:16:54Like this is the, the entire graph and sort of the graphing system is a relatively simple,
0:16:59you know, class, maybe a few hundred lines of code, very performant and straightforward.
0:17:04So like you can go a long way with UI view animation.
0:17:06And I think it's a great place to start anytime you wanted to do some kind of rich animation
0:17:11inside of your applications.
0:17:13Yeah, I would go even further with that and say like, you know, in general, like try things
0:17:18that you assume would be too slow, try it first because you'd be surprised what modern
0:17:26hardware is capable of.
0:17:28Like again, this is something I've run into constantly with voice boost to development
0:17:31is like, I kept thinking I would make an assumption like, oh, there's a certain type of processing
0:17:37that that's pretty sophisticated.
0:17:39It requires like something like a lot of math for every audio sample.
0:17:43And you know, you're playing 44,100 samples per second, possibly in two channels.
0:17:48So two sets of those.
0:17:49And so like that's, that's a lot of math, you know, possibly having to do like significant
0:17:54operations on 88,200 samples per second total and trying to do that in a power envelope
0:18:01that is not going to kill people's battery lives or make their phones hot or get your
0:18:04app killed.
0:18:05And ideally, possibly in the future, run on the Apple Watch as well.
0:18:09And so I would often assume, well, there's a certain kind of processing that I am not
0:18:14going to be able to do.
0:18:15You know, like I would write it because I also use voice boost that the aforementioned
0:18:20command line utility.
0:18:21I also use it myself for pre-processing my podcast files, just to save myself some time.
0:18:25And that's why I might someday release it, but it's not on my front of mind, honestly.
0:18:30For reasons we've talked about on the show before.
0:18:34And so, but you know, I'd have like, you know, the high quality, like mastering quality algorithm.
0:18:40And then I would write a low quality one as well, figuring I'd run that on the phone.
0:18:43And then I'd run it on the phone and I would find that the performance difference really
0:18:47was not very big and that the mastering algorithm runs totally fine and would be like, you know,
0:18:540.2% of the CPU usage during playback or something.
0:18:58Like modern hardware is way faster than you might assume it is.
0:19:03Way faster.
0:19:04And especially in an area like UI views, where that is something that like Apple puts a lot
0:19:10of resources, both software and hardware into making sure that kind of stuff is extremely
0:19:16fast because everything uses it.
0:19:19And it matters a lot.
0:19:21Every app uses views and layers and compositing behind the scenes and everything.
0:19:25Like that's a pretty significant part of the OS and the frameworks.
0:19:28And the GPUs accelerate everything.
0:19:30It's a whole thing.
0:19:31And so you can do so much with that, that like, you know, you don't need to get into
0:19:36like manual image rendering or dropping down to the metal APIs or anything like that for
0:19:41almost any reason.
0:19:42Like you can make a game out of UI views.
0:19:45You could have 100 UI views on the screen animating around, like bouncing around as
0:19:49sprites for a game.
0:19:50It isn't the most performant way to make a game, but you could do it.
0:19:54And if that's what you know and you're just trying to get something done quickly or you
0:19:58wouldn't make it otherwise, just do that.
0:20:01And it's probably fine.
0:20:02- I think there's a lot of these things where like you can get, yeah, it's like you can
0:20:06get the proof of concept at least and probably even potentially better than that, just using
0:20:11UI views.
0:20:12And then like, you know, and just finding interesting ways or creative ways to use them.
0:20:14Like another example of something that I found myself doing several times over my career
0:20:18is applying CA rotation transforms to views.
0:20:23So say for example, you wanted to have a graph that scrolled horizontally, say like pedometer
0:20:30plus plus where it has a bar graph for every day and it scrolls horizontally.
0:20:34What about if you just take a UI table view and rotate it 90 degrees?
0:20:37- Oh my God, does that actually work?
0:20:39- It does.
0:20:40It works fine.
0:20:41- I love that you've tried that.
0:20:44- And you just have to see, you apply a rotation to the view and then you apply a rotation
0:20:47to the sub views to make them so that they're the right way out again.
0:20:52But it totally works.
0:20:53And you can do the same thing with a UI picker.
0:20:56If you want a horizontal picker to be, picker rather than to be vertical, to be horizontal,
0:21:00you can use a UI picker to do that and make it horizontal.
0:21:04And like, it's a little bit crazy and it's like, I've also subsequently moved away from
0:21:09that in pedometer.
0:21:10Like I've sort of implemented my own kind of version based on UI scroll view, but it
0:21:14wasn't because the other version didn't work.
0:21:16It was because I wanted to do more than UI table view could allow me to do.
0:21:20- I hope that somewhere there's a UI kit engineer listening to this right now and either fist
0:21:26pumping because they put in the work to make that work or crying that you're horribly abusing
0:21:33their API.
0:21:34- Well, but I think it's like, it is a great, it's like those are the kinds of little tools
0:21:37that I'm thinking of sometimes where it's like, there's UI kit is such a rich and like,
0:21:44well like sort of battle tested, well written piece of software that like you can do weird
0:21:49stuff with it.
0:21:50It'll probably work like you kind of would hope it would.
0:21:53And you'll have some weird quirks to work around maybe, but like you can do a lot with
0:21:57this kind of stuff.
0:21:58And like many of these kinds of things, like in this case, the right answer is to use a
0:22:02UI collection view now rather than a UI table view.
0:22:06But like you can go a long way with just being thoughtful with like, huh, what if I applied
0:22:11a, you know, what if I applied a transform to a UI view or just, like you're saying,
0:22:18create lots of different views or put views inside of views and like UI kit can handle
0:22:24most of this without a performance issue, without a problem.
0:22:28And it's the best way that I've found to do that first draft of an app.
0:22:32And sometimes that first draft becomes the final draft.
0:22:35But even if it doesn't, it's a really amazing, like the best prototyping tool I found at
0:22:40this point is UI kit.
0:22:41Like beyond doing some kind of like prototyping framework, like these things that you, you
0:22:45know, there's tools that you can do where you are like using some kind of other tool.
0:22:48It's like, no, just use UI views and it'll be fine.
0:22:50- Yeah, I mean, like I think a lot of this wisdom comes down to like don't assume something
0:22:55won't work unless you've actually tried it.
0:22:58Like something that sounds like it shouldn't work, like rotating a table view 90 degrees
0:23:01with a transform to make a horizontal table view.
0:23:04Oh, it's so funny to me.
0:23:06But like, you know, just try it.
0:23:08Like, and I think most of us, myself included, wouldn't have thought to ever even try that.
0:23:14And that's why like people like you who think outside the box, like that's kind of literally
0:23:17what that means.
0:23:18Like, you're just like, hey, this crazy hack might work.
0:23:22Let's see if it does work.
0:23:24- And like appreciate, I think, come to those types of situations with the humility to say
0:23:29this is a hack and I need to keep that in mind and not just like, oh, it sort of works.
0:23:33Like, no, you need to test it.
0:23:34You need to be a bit more thorough with it, but like try it.
0:23:36What's it going to hurt?
0:23:37And like if you can end up with this really, you know, super easy way of doing this and
0:23:42it's doing all the caching and memory performance and all these huge benefits that you might
0:23:46be able to get from using one of the pre-built controls just by tweaking it slightly or transforming
0:23:51it in some way.
0:23:52Like, you can go a long way with that.
0:23:54- That's amazing.
0:23:55- The other kind of interesting thing that I've been doing recently that I just kind
0:23:58of wanted to mention is the way that some kind of tools and things for localization
0:24:03of apps.
0:24:05And so first, the one thing I wanted to point out, and this was something that I only recently
0:24:08discovered, is in iOS 13, we now have per app language settings as one of the options.
0:24:16So if you go to the settings app, scroll down to an application, and it supports localization,
0:24:20you can override the system language for just that application, which is a tremendous tool
0:24:27for development and debugging and testing because you can now very easily and in a very
0:24:33lightweight way change the language of just your application.
0:24:36So I can be like, what does my app look like in German?
0:24:39What does my app look like in French?
0:24:40What does my app look like in Spanish?
0:24:42And I can make those changes very quickly, and it doesn't change the whole system, whereas
0:24:47previously I would have the rather amusing situation where, especially in the non-Roman
0:24:53alphabet languages where I would change the system language into Chinese simplified or
0:24:58Korean or Japanese, and then I have to remember the steps in the settings app that I need
0:25:03to use to go back to the changed language screen and change it back into English, but
0:25:09I have to do it just by memory of it's the fourth item down, then it's the second item
0:25:14down, and then I scroll through this.
0:25:17It's great to just be able to do it, keep the system language as English, and just change
0:25:21the language on a per app basis.
0:25:23So that is a great little tool both for generating screenshots, for helping debug problems with
0:25:28customers, which is how this actually first came to my attention, was it's like there
0:25:32were customers who had issues in a particular language or had a problem, and it's like I
0:25:36can easily, much more easily, get them a screenshot or understand what it is they're seeing by
0:25:41just changing it for the app.
0:25:42So pro tip one.
0:25:44And pro tip two is just something that I, it's like it's one of those things where I'm
0:25:50not sure this is a recommendation so much as just an observation of something that I've
0:25:54done in the past.
0:25:56So often when I'm doing localization, there will be like one line of text that needs to
0:26:00be updated for the purpose of a update, and it's only one line, and I don't really want
0:26:05to go through the fuss of doing the, like going through a localization service and getting
0:26:11it translated and then incorporating it and hoping that the translator understood the
0:26:15nuance of what I meant in this particular case.
0:26:20And so something that I've done many times, which I'm not sure is a recommendation, but
0:26:23it's certainly something to keep in mind, is I think of a string that iOS uses inside
0:26:29of its own apps.
0:26:32So the apps that Apple ships or in iOS itself, and I will essentially just copy whatever
0:26:39it is that they used as their string for a particular localization.
0:26:45So as an example, when I was implementing the system-wide dark mode in Podometer++,
0:26:50one of the things that I needed was a string that basically said, "Do you want to use the
0:26:56setting that you set as an override inside of Podometer, or should it just use the system,
0:27:00or should it just mirror the system setting?"
0:27:03Was basically what I needed a toggle switch to have.
0:27:08Many of us have had this toggle switch implemented in the last few months.
0:27:13But I remember that in the Watch Companion app, in the Notifications Settings area, one
0:27:19of the options is "Mirror My iPhone," which is an option that you can have, "Do you want
0:27:26the notification settings to mirror the iPhone settings, or do you want custom settings?"
0:27:31And so what I did is I just went through and changed my phone to be in German, in French,
0:27:38in Spanish, etc., and I just copied down what Apple had translated "Mirror My iPhone" to
0:27:46into those different languages, which should capture the nuance of what it is I'm trying
0:27:49to do, because it's the same concept.
0:27:51I'm not talking about mirror in terms of the glass thing that you look at, and it
0:27:56reflects back on you.
0:27:57If I had just used a localization service, you could potentially imagine there's a nuance
0:28:01that is lost there.
0:28:03This is a very hard thing to write copy for, even in your own language.
0:28:08And so I was like, "I'll just copy Apple's."
0:28:10And there's a few times that I have to go to Google Translate to work out, "I'll put
0:28:14in the English and then I'll translate into the language and try a few words."
0:28:18Sometimes it's hard to copy, especially in a language that doesn't use the Roman alphabet,
0:28:25but I was able to eventually play around with, "Is it mirror?
0:28:29Is it copy?
0:28:30Is it whatever?"
0:28:31You get to try a bunch of different synonyms, and eventually you get the character that
0:28:36matches the character you're looking for.
0:28:38And that's what I used.
0:28:39And like I said, not necessarily recommended, not great in some ways, because obviously
0:28:43I'm assuming that meaning translates, but so far it's worked.
0:28:48No, I'm going to say that's great.
0:28:50I'm going to override you in that and say that is an awesome hack, because copywriting
0:28:55is something that Apple does very well in the UIs.
0:28:58And it's one of the hardest things to do in an app, especially if you're trying to outsource
0:29:03it to a language that you don't know, so you kind of can't check.
0:29:06So that's actually an awesome hack, because whatever Apple figured for their localizations
0:29:10is not only saving you time, it's probably better than anything you would have gotten
0:29:13back.
0:29:14Yeah.
0:29:15So anyway, it's just a fun little thing that if you can think of a place or structuring
0:29:19your copy so that it matches Apple's copy, you can save yourself a lot of time.
0:29:23And apparently, according to you, it's even better.
0:29:26So I'll take that and recommend it now as a way to speed up your localization process,
0:29:33especially for kind of simple things.
0:29:35And I suppose you could also use it to validate externally produced localizations.
0:29:38You could take that approach as well if you wanted to go that way.
0:29:40But either way, fun little trick.
0:29:42That's awesome.
0:29:43Thanks for listening, everybody.
0:29:44And we'll talk to you in two weeks.
0:29:46Bye.
0:29:47[BLANK_AUDIO]