Apple-like

Craftsmanship & Consideration

In the last few months there has been a lot of discussion of people’s hopes for the future of Apple. With the announced leadership changes, it is a logical period of reflection and projection of hopes for the future.

A recurring theme I’ve heard is a desire for Apple to “return to its roots” or “go back to what made it great”. I don’t personally feel those feelings very much. Maybe I’d describe its situation as a ship which has become a bit unbalanced by some structural choices and so is listing to the side, meaning it takes more intentional effort to stay on course. I would gladly appreciate it if new leadership were able to shift some ballast around to make the ship run truer, but the general direction remains unchanged.

A more productive line of thinking this conversation has prompted in me, which I’ve been ruminating on for weeks, is what exactly is Apple-like. What makes Apple…Apple?

I am proud to call myself an “Apple Developer” and not just because I develop on Apple platforms, but because for the 18 years I’ve been working on apps I’ve aspired towards building in a way which is Apple-like in style. I realized, however, that I didn’t have a very specific definition of what that actually meant, so over the course of a lot of walking and running in the hills around my house I have tried to narrow it down to a few concise maxims which summarize the type of company and products I want to aspire to building. I ended up with three goals which I think capture the essence of what being an Apple-like builder means to me.

The Best, and then Better

First and foremost there is a fundamental desire to make things in as high a quality way as is possible. To be constantly striving towards making things without cut corners or lazy compromises. That I’m essentially never satisfied with my work, and I am always thinking about how things could be better. The goal is to be the best in whatever category you are creating. You will never actually arrive, but this mindset clarifies thinking and helps keep you relentlessly improving.

It does, however, also create a situation which is incredibly dangerous. If you are always striving towards improving quality you will eventually end up with a surplus of user expectation. In my experience this surplus is incredibly precarious because once you are better than your competitors there will always be a temptation to let up on this pursuit and instead spend some of that surplus on things which don’t improve the user’s experience. It is so easy at this point to do the thing which worsens the user experience but helps the bottom line, with the justification that you’ll still be the best.

Which is why the second part of this maxim is that you have to not only strive to be the best, but then once you get ahead keep working on the marginal gains to relentlessly improve. You can’t just be “The Best”, you have to also still be always “Better”.

Excellence for Everyone

I want to create excellent products which are available to everyone. There are two primary ways I think about this, affordability and accessibility.

Apple products are not cheap, but I would argue that they are generally affordable (as shown by the literal billions of their products which have been sold). There is a big difference between something being expensive and being exclusive. Consider, for example, the difference between a Hermès Watch strap and an Apple-branded one. The former is exclusive in its pricing; the latter is simply expensive.

Price is one of the fundamental design considerations of a product. It directly determines a huge number of the aspects of a product. So often in my own work I’ve struggled with the feeling that “a cheap price is a better price”. I think something I’ve learned from the way Apple runs its business is that if price is the thing you are optimizing for then your product will inevitably suffer. You want a price which supports quality. However, things will go sideways if you ever move beyond expensive and start to be exclusionary in your pricing.

The other side of this relates to building products in a way that the widest number of possible people can use them. This can straightforwardly take the classic forms of accessibility like VoiceOver or Dynamic Type. But more often, it is just generally building products which can relate to as wide a cross section of the world as possible. I want to make designs which are intuitive and approachable. There is a time and place for complexity in an app, but for a design to be Apple-like it will usually hide that complexity behind opinionated choices which invite the user into a comfortable, confident use.

Beneficial and Brilliant

The products we all make should be beneficial for the lives of the users we are building them for and solve their problems in novel, delightful ways.

Building products which are so attractive to users that they want to spend meaningful amounts of their lives using them comes with a tremendous responsibility to make those experiences beneficial to those users. There are a huge array of psychologically manipulative ways we can affect our users while they use our apps, but these are typically beneficial to the developer, not the user.

The smartphone has such incredibly high daily usage in our lives that it can be a tremendous influence for either good or ill. There is an honesty in this area which is very important to constantly wrestle with. There are countless ways to improve the superficial measurements of a product’s success, which are not beneficial to our users. Instead, striving towards the most user benefit will likely be a slower impact in the short-term but a better one in the long-term.

This beneficial impact should, whenever possible, come in the form of brilliant solutions to problems users might not even be aware they have. This is the old “Surprise and Delight” design goal. This kind of design philosophy comes from a deeper understanding of what a user wants. Rather than just considering the superficial need, you dig a bit deeper until you find the brilliant solution to the fundamental need which will improve the user’s life.

The Compass

These three goals are in aggregate a useful north-star to consistently align design and development efforts. I know full well that the realities and pressures of life will make it impossible to actually ever attain them. The utility of a compass isn’t that it allows you to walk in a perfectly straight line, but instead that wherever you find yourself you’ll know which way to go to make progress towards your intended destination.

David Smith




Six Years Perfecting Maps on watchOS

Design Diary

Cloughhead

I love going on wilderness adventures. I am rarely happier than when I am far off into the mountains without a soul in sight. As a result, I have spent a lot of time learning how to safely explore and navigate when I’m away from civilization. The most important habit I’ve found for not getting lost is to be very regular in checking your location as you go, and the best way I’ve found to do that is to have a map on my wrist.

Pedometer++

For more than six years I’ve been working towards creating the best possible mapping experience on the Apple Watch. With yesterday’s launch of Pedometer++ 8, I feel like this design journey has reached a meaningful destination. I would contend that Pedometer++’s watchOS mapping support is the absolute best available on the App Store.

So I wanted to walk through the journey it took to get here.

Early Efforts

I have wanted a good map on my wrist since the Apple Watch launched. This wasn’t realistically possible until watchOS 6, which brought SwiftUI to the platform and, for the first time, made “real” apps possible. But in those early days, the screens were tiny, and the processors slow. I couldn’t quite get to where I wanted.

This was my very first attempt that shipped in Pedometer++. These maps were generated completely on the server, which involved sending the relevant workout data roundtrip every time I wanted to refresh the display. This system let me validate the idea, but it was never going to be practically useful for navigation or regular use, and could never work offline.

Custom Mapping Engine

I knew that if I wanted to make progress towards this goal, I’d need to work at a lower level, so I got to work building a fully SwiftUI-native map rendering engine. SwiftUI was the only choice because it’s all that watchOS supported, and proved to be helpful for putting maps into widgets, which also only support SwiftUI.

In 2021, I got this engine to a place where I could reliably and performantly render a map on watchOS. With it, I can render any tile-based maps and overlay location information on top.

Map Designs

Next came the question of how best to surface data to users. App design on watchOS is a really fun — but frustrating — challenge. You are designing for a relatively tiny screen, which must be operated one-handed. In this case, I want the user to be able to read the map and use it to navigate, while also having access to other workout-related information.

This began a long series of design attempts, most of which (if I’m being honest) were kinda awful.

Bad designs

In the end, I settled on a “modal” approach where the user can switch between a map screen and a metrics screen using a button on the top-left corner.

Modal Maps

This interface provides one context where the user can freely pan/zoom around the map and another where I can use the more standard watchOS tabbed page interface for metrics and controls. I shipped this to Pedometer++, but there was always something that didn’t quite sit right with me about it.

This design felt like a compromise, and not in a good way. I felt that in order to achieve the goal of making the map interactive, I couldn’t have the map be part of any UI structure that involved swipes. As the screens on Apple Watches got larger, it felt less needed in order to give the map enough space to be useful.

So I set about trying alternative designs. SO many designs.

Many more designs

For a while, I thought that I needed to find a way to put the metrics at the bottom of the screen. However, that would lead to other problems on longer outings or for workouts that aren’t navigation-focused. So I kept iterating and came up with even more designs.

Even more designs

All of these designs suffered from the same fundamental issue: they required the app to display only a fixed set of fields at a time.

I could make the interface configurable, but one of the fundamental rules of watchOS design is that you should avoid any interaction that takes more than a few seconds on the watch. Any user-configurable setup is inherently fiddly, so I didn’t like this approach.

Dark Mode, Liquid Glass, & Cartography

Around the same time I was still wrestling with the design challenges of how best to structure the app, Apple announced watchOS 26, and the arrival of Liquid Glass. One of the core design aspects of Liquid Glass is layering stacking elements on top of each other, but another is the types of colors that work best with each other.

I was previously using Thunderforest Outdoors as my basemap for the app. I love the content this map includes, but when I started overlaying glassy elements over it I found that it wasn’t well-suited for Liquid Glass.

So… I commissioned a custom map. Working with the incredible cartographer Andy Allan, we created a completely new basemap that would look fantastic with Liquid Glass.1

We simplified the map visually, increased the contrast of the elements, and made the map elements more saturated to prevent them from becoming a muddy mess when shown below glass.

With this work done, I had another opportunity: I could finally have a dark mode variant of the map tiles. While helpful on iOS, this really shines on watchOS. Andy and I really worked toward something which would be incredibly legible at arm’s length.

The result of these efforts is that now I have a great map for watchOS… but a design that didn’t match that greatness.

Striving for Great

I kept trying. To get me out of my design rut, I enlisted the help of the fantastic designer Rafa Conde. I needed a fresh set of eyes on this and very quickly, this partnership paid off. They proposed a variety of alternative layouts, but when I saw this one I knew it was the one.

The layering of the metrics on the top-left corner, with the map being the top page of a vertical stack, was the correct answer. This design handles interactivity by requiring a tap on the map first to enter “browse mode”.

Tweaking and Polishing

Now that I had the overall concept locked in, the real fun began, actually building the app and dialing in all the details. I fairly quickly took Rafa’s concept and turned it into a working prototype. This let me validate the idea in the field… literally. After walking a few hundred miles with it, I was confident it was the correct approach.

Next, I needed to dial in the font and make more subtle design choices.

Map fonts

After a bit more iteration, I arrived at the design that shipped yesterday. It is legible, useful, and (in my humble opinion) beautiful.

It feels really good to be able to cap off this six-year journey with a design I couldn’t be more proud of. This screen represents so much accumulated effort and learning. It finally gives me a design which feels native on the platform, but also novel and unique.

Here is the evolution of this design over the last six years:

Postscript: Considering MapKit

While my work on watchOS mapping massively predates the arrival of Apple’s MapKit onto the platform, it is probably worth explaining why I decided to do all of this custom work to avoid using it.

Fundamentally, I find that MapKit is great for basic uses, but doesn’t provide nearly the level of configurability and utility which I want Pedometer++ to offer. For example:

  • MapKit on watchOS always shows in dark mode, which generally is a good default, but closes the door on some accessibility and user choice reasons. I needed it to be a user-selectable option.
  • While MapKit on watchOS has gotten better over time in terms of what you can do with it, I still find it a bit limiting in terms of animations and overlays.
  • MapKit’s coverage is improving with regards to topographic contours and trail marking, but there are far too many places where the MapKit map is essentially blank, but I know there should be more rich details available. For example, here is my map vs MapKit at the trailhead of one of my favorite hikes in Scotland.

MapKit comparision

  1. I still find it so cool that my work on this allows me to say that I “commissioned a cartographer” to work on something for me. 😁 

David Smith




Pedometer++ v8: Designed for Adventure

Today I’m beyond delighted to announce the release of Pedometer++ version 8. I worked with legendary designer Rafa Conde to re-design the appearance and layout of the watchOS app to make it the most capable, yet intuitive, walking app on the App Store.

Pedometer++ has been on the Apple Watch from day one twelve years ago. Over that time I’ve built dozens of designs and features, today’s redesign learns from that journey and arrives at an incredible place.

The Home Screen has been clarified to make it more legible at a glance. A bright, colorful display of your daily step count makes it easy to see your progress towards your goals. This animates as you move and celebrates when you reach your goal.

Swiping up brings you to straightforward workout list screen where you can choose from a walk, run or hike. If you have a planned route for your outing you can select the route you configured on your iPhone here.

There is a new Expedition Mode workout type which dramatically reduces the battery usage during adventures to allow for longer outings. In my testing I found that this mode can extend your watch’s battery life by up to 40%.

If you’re a premium subscriber when you start a workout you’ll be immediately brought to your new maps screen which shows your workout on a live updating map. This map will overlay your planned route, if selected.

This screen now features our completely custom dark mode map. I worked with a cartographer to design a map which looks perfectly at home on the Apple Watch, which is highly legible even at arms length and includes all the topographic and wayfinding information you need to keep you on track.

You can also select a light mode if you prefer. If you are in the United Kingdom, you can also select to use an Ordnance Survey map.

The overall structure of the workout app has been simplified to make it easier to quickly navigate. Swiping to the left from any screen brings you to the workout controls. Swiping to the right brings up the media controls.

Swiping up from the map will bring you to the detailed workout stats, organized by type. You can quickly see your current heart rate zone, your speed or the elevation gain you’ve accomplished on the walk.

This new layout allows for flexibility without fiddily-ness. I’ve taken this new layout out on dozens of all-day adventures and I can say with confidence it gets the job done. Pedometer++ is still the most capable workout app on the App Store, but now provides that power without visual complexity.


David Smith




Generally Useful Prompts

The last few months have involved a major shift in how I do my work. With things like the Codex app and GPT-5.3+ reaching a level of code quality and consistency which has made them properly helpful. While my use of these tools for general purpose programming is still something I haven’t fully settled my workflow for, there are several uses for these tools which I have found I use very regularly.

These are prompts which I find are just generally useful, without requiring changing the inherent workflows I use for programming my apps. While I’m starting to tactically deploy agents for general programming tasks, I feel like the line of when I manually code and let the agent do it is currently more fluid.

Previews

Add a SwiftUI preview for TrainingBlockDraftEditorView, including data variants for each of the flows through the view

SwiftUI previews are huge benefit for my productivity when iterating on the UI/UX of a view, but I find the setup and creation of the data needed to drive them a bit of a pain to setup. But this is a perfect thing for an LLM to generate. I even had a great use recently where I was working on a weather view and I asked it to create different data blocks for different locations (to see how rainy vs sunny would render) and it worked out the API keys necessary to do some CURL requests to get actual data to use.

Realtime Documentation

Look at the publishSnapshot: method. Identify all the uses of it and determine what it does and how it is used. Describe its function and how it acts in all different uses of it

While I in theory it would be good for every one of my methods to been neatly documented, in practice that almost never happens. I work by myself in the code, so rarely need to document things like I would if I worked as part of a larger team. All the same, sometimes I find old code which I don’t fully remember or am making a change to something which I want to have full understanding of all uses of it. This ‘realtime documentation’ works a treat and has the added advantage over static documentation of being 100% up-to-date (rather than slowly slipping out of sync with reality of time).

Newly Localizable Strings

Look at the git diff since XXXX and locate any newly introduced user visible strings in the app which need to be localized. Add entries for each of these strings to each language supported by this app with relevant translations.

A pattern I’ll use for many of these prompts is the “Look at the diff since XXXX” where XXXX is the git hash of the last released version. This helps narrow down the changes and lets me isolate the updates to the relevant, new code.

In this case I want to have it seek out any newly added user-facing strings which were introduced and then add translations to the .strings files for each supported language. For years I’ve used LLMs to power the baseline translations I use in the app, so this shortcuts the process. It also has helped me to identify spots where I was using strings in a way which wouldn’t actually get triggered by the localization system (like a string literal passed into a view).

Testing plan

Look at the git diff since XXXX and create a recommended testing plan to provide good coverage of the areas of the app which are either new or were changed. Including likely user paths which could now include incorrect behaviour. Generate the export as a nicely formatted PDF checklist.

This works to evaluate all the code which has changed and then it gives me a list of things which I should do to make sure the app update didn’t introduce regressions. This has a few times identified little user paths which I might not have thought to test, or just generally helps me find areas to be more thorough with.

New Bugs

Look at the git diff since XXXX and explore whether the newly added code has introduced any bugs or likely unexpected results. Consider how the newly added code interacts with existing code and whether it will change existing behavior. Also, identify any areas where the newly added code is inconsistent with the general style and design pattern of the related, existing code.

The hit rate for this prompts I relatively low (maybe 20%), but the reality is I am always very grateful for any bug which I can find before it ships to customers, so having a second opinion on things is great.

Release Notes

Look at the git diff since XXXX and identify any new features or changes which would be visible to the user. Write a summarized release notes for the changes organized by size of the change (Major features, minor features, bugfixes).

This isn’t something which I expect to use directly for the user, but is a very helpful baseline for the creation of the real release notes. Also, this has helped me when I’ve been working on a larger, more sprawling update and I forget all of what I’ve done.

David Smith




Display Zoom Statistics

In Widgetsmith 8.2 we added the ability to give your widgets a ‘clear’ background. This isn’t actually clear (since iOS doesn’t allow that without private API use), but instead just crops part of your home screen wallpaper and uses that as the background.

In order for that to work I need to know precisely where each and every widget is on each and every iPhone model. This involved a massive process of screenshotting and a custom app for doing pixel precise analysis. There are 31 iPhone models which support iOS 26 (which I required for this update), so for each of these I needed to collect nine screenshots.

That all went well, but then I was faced with a slight dilemma about how/if I should support Display Zoom. This is a feature which increases the effective size of your iPhone’s controls by rendering your iPhone’s screen at a lower resolution and then enlarging it to fill the actual screen.

Since Display Zoom creates a new virtual resolution for the iPhone I would need to duplicate all the work I did to support the regular widget positions for each iPhone. This effort is made doubly tricky because the iOS simulator doesn’t properly render Display Zoom so I’d have to rely on screenshots from devices to which I have physical access.

To better inform this decision I went looking for statistics about the usage of Display Zoom, but couldn’t really find anything. So in a recent update to Widgetsmith I built in analytics code which reported Display Zoom usage.

What I found was that overall usage of Display Zoom was at 1.9%, which was lower than I would have guessed. For Widgetsmith I see 18% of users with their Text Size set to something larger than the default size, so I’d have guessed the number would have been much higher than 1.9%.

But that helps me to feel better about not supporting Display Zoom for this feature. That is simply not enough users for it to be viable to sustain the effort supporting it would require.

Here is a breakdown of the Display Zoom adoption by iPhone model family. It seems to skew heavily towards the smallest and largest iPhones.

CategoryUserbaseDisplay Zoom
SE 0.5%4.90%
Mini 1.2%4.60%
Air 0.2%3.80%
Plus 5.0%3.20%
Pro Max 20.3%2.70%
Regular 50.9%1.80%
e 1.0%1.80%
Pro 10.8%0.90%
Overall1.90%
David Smith